diff --git a/config/webpack.config.dev.js b/config/webpack.config.dev.js
index 2a163eb4fa0..9cf72bff3f1 100644
--- a/config/webpack.config.dev.js
+++ b/config/webpack.config.dev.js
@@ -10,7 +10,6 @@
 var path = require('path');
 var autoprefixer = require('autoprefixer');
 var webpack = require('webpack');
-var HtmlWebpackPlugin = require('html-webpack-plugin');
 
 // TODO: hide this behind a flag and eliminate dead code on eject.
 // This shouldn't be exposed to the user.
@@ -25,8 +24,6 @@ if (isInDebugMode) {
 }
 var srcPath = path.resolve(__dirname, relativePath, 'src');
 var nodeModulesPath = path.join(__dirname, '..', 'node_modules');
-var indexHtmlPath = path.resolve(__dirname, relativePath, 'index.html');
-var faviconPath = path.resolve(__dirname, relativePath, 'favicon.ico');
 var buildPath = path.join(__dirname, isInNodeModules ? '../../..' : '..', 'build');
 
 module.exports = {
@@ -34,7 +31,7 @@ module.exports = {
   entry: [
     require.resolve('webpack-dev-server/client') + '?http://localhost:3000',
     require.resolve('webpack/hot/dev-server'),
-    path.join(srcPath, 'index')
+    path.join(srcPath, 'client/index')
   ],
   output: {
     // Next line is not used in dev but WebpackDevServer crashes without it:
@@ -92,11 +89,6 @@ module.exports = {
     return [autoprefixer];
   },
   plugins: [
-    new HtmlWebpackPlugin({
-      inject: true,
-      template: indexHtmlPath,
-      favicon: faviconPath,
-    }),
     new webpack.DefinePlugin({ 'process.env.NODE_ENV': '"development"' }),
     // Note: only CSS is currently hot reloaded
     new webpack.HotModuleReplacementPlugin()
diff --git a/config/webpack.config.prod.js b/config/webpack.config.prod.js
index a5c52513f2b..d15e7edf6e9 100644
--- a/config/webpack.config.prod.js
+++ b/config/webpack.config.prod.js
@@ -10,7 +10,6 @@
 var path = require('path');
 var autoprefixer = require('autoprefixer');
 var webpack = require('webpack');
-var HtmlWebpackPlugin = require('html-webpack-plugin');
 var ExtractTextPlugin = require('extract-text-webpack-plugin');
 var url = require('url');
 
@@ -24,9 +23,7 @@ if (process.argv[2] === '--debug-template') {
 }
 var srcPath = path.resolve(__dirname, relativePath, 'src');
 var nodeModulesPath = path.join(__dirname, '..', 'node_modules');
-var indexHtmlPath = path.resolve(__dirname, relativePath, 'index.html');
-var faviconPath = path.resolve(__dirname, relativePath, 'favicon.ico');
-var buildPath = path.join(__dirname, isInNodeModules ? '../../..' : '..', 'build');
+var buildPath = path.join(__dirname, isInNodeModules ? '../../..' : '..', 'build/client');
 var homepagePath = require(path.resolve(__dirname, relativePath, 'package.json')).homepage;
 var publicPath = homepagePath ? url.parse(homepagePath).pathname : '/';
 if (!publicPath.endsWith('/')) {
@@ -37,7 +34,7 @@ if (!publicPath.endsWith('/')) {
 module.exports = {
   bail: true,
   devtool: 'source-map',
-  entry: path.join(srcPath, 'index'),
+  entry: path.join(srcPath, 'client/index'),
   output: {
     path: buildPath,
     filename: '[name].[chunkhash].js',
@@ -98,23 +95,6 @@ module.exports = {
     return [autoprefixer];
   },
   plugins: [
-    new HtmlWebpackPlugin({
-      inject: true,
-      template: indexHtmlPath,
-      favicon: faviconPath,
-      minify: {
-        removeComments: true,
-        collapseWhitespace: true,
-        removeRedundantAttributes: true,
-        useShortDoctype: true,
-        removeEmptyAttributes: true,
-        removeStyleLinkTypeAttributes: true,
-        keepClosingSlash: true,
-        minifyJS: true,
-        minifyCSS: true,
-        minifyURLs: true
-      }
-    }),
     new webpack.DefinePlugin({ 'process.env.NODE_ENV': '"production"' }),
     new webpack.optimize.OccurrenceOrderPlugin(),
     new webpack.optimize.DedupePlugin(),
@@ -131,6 +111,13 @@ module.exports = {
         screw_ie8: true
       }
     }),
-    new ExtractTextPlugin('[name].[contenthash].css')
+    new ExtractTextPlugin('[name].[contenthash].css'),
+    function() {
+      this.plugin('done', function(stats) {
+        require('fs').writeFileSync(
+          path.join(buildPath, 'stats.json'),
+          JSON.stringify(stats.toJson().assetsByChunkName));
+      });
+    }
   ]
 };
diff --git a/config/webpack.config.server.dev.js b/config/webpack.config.server.dev.js
new file mode 100644
index 00000000000..dad23c8b955
--- /dev/null
+++ b/config/webpack.config.server.dev.js
@@ -0,0 +1,68 @@
+var path = require('path');
+var fs = require('fs');
+var webpack = require('webpack');
+
+var isInNodeModules = 'node_modules' ===
+  path.basename(path.resolve(path.join(__dirname, '..', '..')));
+var relativePath = isInNodeModules ? '../../..' : '..';
+var isInDebugMode = process.argv.some(arg =>
+  arg.indexOf('--debug-template') > -1
+);
+if (isInDebugMode) {
+  relativePath = '../template';
+}
+
+var srcPath = path.resolve(__dirname, relativePath, 'src');
+var nodeModulesPath = path.join(__dirname, '..', 'node_modules');
+var buildPath = path.join(__dirname, isInNodeModules ? '../../..' : '..', 'build/server');
+
+const nodeModules = fs.readdirSync(nodeModulesPath)
+  .filter(entry => ['.bin'].indexOf(entry) === -1)
+  .reduce((reduction, entry, foo) => {
+    const objectWithCommonJsModule = {};
+    objectWithCommonJsModule[entry] = `commonjs ${entry}`;
+    return Object.assign(reduction, objectWithCommonJsModule);
+  }, {});
+
+module.exports = {
+  entry: path.join(srcPath, 'server/server'),
+  target: 'node',
+  debug: true,
+  watch: true,
+  inline: true,
+  devtool: 'eval',
+  output: {
+    path: buildPath,
+    filename: 'server-dev.js',
+    publicPath: '/'
+  },
+  externals: nodeModules,
+  module: {
+    loaders: [
+      {
+        test: /\.js$/,
+        include: srcPath,
+        loader: 'babel',
+        query: require('./babel.dev')
+      },
+      {
+        test: /\.json$/,
+        loader: 'json'
+      },
+      {
+        test: /\.(jpg|png|gif|eot|svg|ttf|woff|woff2)$/,
+        loader: 'file?emitFile=false',
+      },
+      {
+        test: /\.(mp4|webm)$/,
+        loader: 'url?limit=10000'
+      }
+    ]
+  },
+  resolve: {
+    extensions: ['', '.js']
+  },
+  plugins: [
+    new webpack.DefinePlugin({ 'process.env.NODE_ENV': '"development"' }),
+  ]
+};
diff --git a/config/webpack.config.server.prod.js b/config/webpack.config.server.prod.js
new file mode 100644
index 00000000000..bede5a07b30
--- /dev/null
+++ b/config/webpack.config.server.prod.js
@@ -0,0 +1,80 @@
+var path = require('path');
+var fs = require('fs');
+var webpack = require('webpack');
+
+var isInNodeModules = 'node_modules' ===
+  path.basename(path.resolve(path.join(__dirname, '..', '..')));
+var relativePath = isInNodeModules ? '../../..' : '..';
+var isInDebugMode = process.argv.some(arg =>
+  arg.indexOf('--debug-template') > -1
+);
+if (isInDebugMode) {
+  relativePath = '../template';
+}
+
+var srcPath = path.resolve(__dirname, relativePath, 'src');
+var nodeModulesPath = path.join(__dirname, '..', 'node_modules');
+var buildPath = path.join(__dirname, isInNodeModules ? '../../..' : '..', 'build/server');
+
+const nodeModules = fs.readdirSync(nodeModulesPath)
+  .filter(entry => ['.bin'].indexOf(entry) === -1)
+  .reduce((reduction, entry, foo) => {
+    const objectWithCommonJsModule = {};
+    objectWithCommonJsModule[entry] = `commonjs ${entry}`;
+    return Object.assign(reduction, objectWithCommonJsModule);
+  }, {});
+
+module.exports = {
+  entry: path.join(srcPath, 'server/server'),
+  target: 'node',
+  devtool: 'source-map',
+  output: {
+    path: buildPath,
+    filename: 'server.js',
+    publicPath: '/'
+  },
+  externals: nodeModules,
+  module: {
+    loaders: [
+      {
+        test: /\.js$/,
+        include: srcPath,
+        loader: 'babel',
+        query: require('./babel.prod')
+      },
+      {
+        test: /\.json$/,
+        loader: 'json'
+      },
+      {
+        test: /\.(jpg|png|gif|eot|svg|ttf|woff|woff2)$/,
+        loader: 'file?emitFile=false',
+      },
+      {
+        test: /\.(mp4|webm)$/,
+        loader: 'url?limit=10000'
+      }
+    ]
+  },
+  resolve: {
+    extensions: ['', '.js']
+  },
+  plugins: [
+    new webpack.DefinePlugin({ 'process.env.NODE_ENV': '"production"' }),
+    new webpack.optimize.OccurrenceOrderPlugin(),
+    new webpack.optimize.DedupePlugin(),
+    new webpack.optimize.UglifyJsPlugin({
+      compressor: {
+        screw_ie8: true,
+        warnings: false
+      },
+      mangle: {
+        screw_ie8: true
+      },
+      output: {
+        comments: false,
+        screw_ie8: true
+      }
+    })
+  ]
+};
diff --git a/foobar/package.json b/foobar/package.json
new file mode 100644
index 00000000000..6f84cbe0cc4
--- /dev/null
+++ b/foobar/package.json
@@ -0,0 +1 @@
+{"name":"foobar","version":"0.0.1","private":true}
\ No newline at end of file
diff --git a/package.json b/package.json
index 0bf487482aa..d7efc08c545 100644
--- a/package.json
+++ b/package.json
@@ -48,11 +48,12 @@
     "extract-text-webpack-plugin": "1.0.1",
     "file-loader": "0.9.0",
     "fs-extra": "^0.30.0",
-    "html-webpack-plugin": "2.22.0",
     "json-loader": "0.5.4",
     "opn": "4.0.2",
     "postcss-loader": "0.9.1",
+    "request": "^2.74.0",
     "rimraf": "2.5.3",
+    "single-child": "^0.3.4",
     "style-loader": "0.13.1",
     "url-loader": "0.5.7",
     "webpack": "1.13.1",
diff --git a/scripts/build.js b/scripts/build.js
index 7acb199652d..9d7e59d5514 100644
--- a/scripts/build.js
+++ b/scripts/build.js
@@ -12,7 +12,8 @@ process.env.NODE_ENV = 'production';
 var path = require('path');
 var rimrafSync = require('rimraf').sync;
 var webpack = require('webpack');
-var config = require('../config/webpack.config.prod');
+var configClient = require('../config/webpack.config.prod');
+var configServer = require('../config/webpack.config.server.prod');
 
 var isInNodeModules = 'node_modules' ===
   path.basename(path.resolve(path.join(__dirname, '..', '..')));
@@ -24,7 +25,9 @@ var packageJsonPath = path.join(__dirname, relative, 'package.json');
 var buildPath = path.join(__dirname, relative, 'build');
 rimrafSync(buildPath);
 
-webpack(config).run(function(err, stats) {
+webpack(configServer).run(() => {});
+
+webpack(configClient).run(function(err, stats) {
   if (err) {
     console.error('Failed to create a production build. Reason:');
     console.error(err.message || err);
diff --git a/scripts/start.js b/scripts/start.js
index 8753c34d68d..93dcb50bcce 100644
--- a/scripts/start.js
+++ b/scripts/start.js
@@ -12,19 +12,30 @@ process.env.NODE_ENV = 'development';
 var path = require('path');
 var chalk = require('chalk');
 var webpack = require('webpack');
+var request = require('request');
+var UrlResolver = require('url');
+var SingleChild = require('single-child');
 var WebpackDevServer = require('webpack-dev-server');
-var config = require('../config/webpack.config.dev');
+var configClient = require('../config/webpack.config.dev');
+var configServer = require('../config/webpack.config.server.dev');
 var execSync = require('child_process').execSync;
 var opn = require('opn');
 
+process.on('uncaughtException', err => console.error(err));
+
+const SERVER_PATH = 'http://localhost:3001';
+const MAX_PROXY_RETRIES = 3;
+
+let server = null;
+
 // TODO: hide this behind a flag and eliminate dead code on eject.
 // This shouldn't be exposed to the user.
-var handleCompile;
+var handleCompileClient;
 var isSmokeTest = process.argv.some(arg =>
   arg.indexOf('--smoke-test') > -1
 );
 if (isSmokeTest) {
-  handleCompile = function (err, stats) {
+  handleCompileClient = function (err, stats) {
     if (err || stats.hasErrors() || stats.hasWarnings()) {
       process.exit(1);
     } else {
@@ -61,16 +72,37 @@ function formatMessage(message) {
     .replace('./~/css-loader!./~/postcss-loader!', '');
 }
 
+function openBrowser() {
+  if (process.platform === 'darwin') {
+    try {
+      // Try our best to reuse existing tab
+      // on OS X Google Chrome with AppleScript
+      execSync('ps cax | grep "Google Chrome"');
+      execSync(
+        'osascript ' +
+        path.resolve(__dirname, './openChrome.applescript') +
+        ' http://localhost:3000/'
+      );
+      return;
+    } catch (err) {
+      // Ignore errors.
+    }
+  }
+  // Fallback to opn
+  // (It will always open new tab)
+  opn('http://localhost:3000/');
+}
+
 function clearConsole() {
   process.stdout.write('\x1B[2J\x1B[0f');
 }
 
-var compiler = webpack(config, handleCompile);
-compiler.plugin('invalid', function () {
+function webpackOnInvalid() {
   clearConsole();
-  console.log('Compiling...');
-});
-compiler.plugin('done', function (stats) {
+  console.log('Compiling...');  
+}
+
+function webpackOnDone(stats) {
   clearConsole();
   var hasErrors = stats.hasErrors();
   var hasWarnings = stats.hasWarnings();
@@ -119,35 +151,63 @@ compiler.plugin('done', function (stats) {
     console.log('Use ' + chalk.yellow('// eslint-disable-next-line') + ' to ignore the next line.');
     console.log('Use ' + chalk.yellow('/* eslint-disable */') + ' to ignore all warnings in a file.');
   }
-});
+}
 
-function openBrowser() {
-  if (process.platform === 'darwin') {
-    try {
-      // Try our best to reuse existing tab
-      // on OS X Google Chrome with AppleScript
-      execSync('ps cax | grep "Google Chrome"');
-      execSync(
-        'osascript ' +
-        path.resolve(__dirname, './openChrome.applescript') +
-        ' http://localhost:3000/'
-      );
-      return;
-    } catch (err) {
-      // Ignore errors.
-    }
-  }
-  // Fallback to opn
-  // (It will always open new tab)
-  opn('http://localhost:3000/');
+function exponentialBackoff(step) {
+  return Math.pow(2, step);
 }
 
-new WebpackDevServer(compiler, {
+const clientCompiler = webpack(configClient, handleCompileClient);
+clientCompiler.plugin('invalid', webpackOnInvalid);
+clientCompiler.plugin('done', webpackOnDone);
+
+// Here's the server compiler
+webpack(configServer, function(error, stats) {
+  webpackOnDone(stats);
+
+  if (!server) {
+    server = new SingleChild('node', ['build/server/server-dev.js'], {
+      stdio: [0, 1, 2]
+    });
+    server.start();
+  } else {
+    server.restart();
+  }
+});
+
+const devServer = new WebpackDevServer(clientCompiler, {
   historyApiFallback: true,
   hot: true, // Note: only CSS is currently hot reloaded
-  publicPath: config.output.publicPath,
+  publicPath: configClient.output.publicPath,
   quiet: true
-}).listen(3000, function (err, result) {
+});
+
+devServer.use('/', (req, res) => {
+  const url = UrlResolver.resolve(SERVER_PATH, req.url);
+
+  let retries = 0;
+  const proxyRequest = () => {
+    req
+      .pipe(request(url))
+      .on('error', error => {
+        if (retries <= MAX_PROXY_RETRIES) {
+          setTimeout(proxyRequest, exponentialBackoff(retries) * 1000)
+          retries++;
+        } else {
+          console.error(error);
+
+          res
+            .status(500)
+            .send('Proxy does not work');
+        }
+      })
+      .pipe(res);
+  }
+
+  proxyRequest();
+});
+
+devServer.listen(3000, function (err, result) {
   if (err) {
     return console.log(err);
   }
@@ -157,3 +217,5 @@ new WebpackDevServer(compiler, {
   console.log();
   openBrowser();
 });
+
+
diff --git a/template/package.json b/template/package.json
index e74146c7029..02c2ec61e2f 100644
--- a/template/package.json
+++ b/template/package.json
@@ -7,10 +7,12 @@
   },
   "dependencies": {
     "react": "^15.2.1",
-    "react-dom": "^15.2.1"
+    "react-dom": "^15.2.1",
+    "express": "^4.13.4"
   },
   "scripts": {
     "start": "react-scripts start",
+    "start:production": "node build/server/server.js",
     "build": "react-scripts build",
     "eject": "react-scripts eject"
   }
diff --git a/template/src/App.css b/template/src/client/App.css
similarity index 100%
rename from template/src/App.css
rename to template/src/client/App.css
diff --git a/template/src/App.js b/template/src/client/App.js
similarity index 95%
rename from template/src/App.js
rename to template/src/client/App.js
index d7d52a7f38a..75aea8d9398 100644
--- a/template/src/App.js
+++ b/template/src/client/App.js
@@ -1,6 +1,5 @@
 import React, { Component } from 'react';
 import logo from './logo.svg';
-import './App.css';
 
 class App extends Component {
   render() {
diff --git a/template/src/index.css b/template/src/client/index.css
similarity index 100%
rename from template/src/index.css
rename to template/src/client/index.css
diff --git a/template/src/index.js b/template/src/client/index.js
similarity index 89%
rename from template/src/index.js
rename to template/src/client/index.js
index 54c5ef1a427..02fb078e791 100644
--- a/template/src/index.js
+++ b/template/src/client/index.js
@@ -1,7 +1,9 @@
 import React from 'react';
 import ReactDOM from 'react-dom';
 import App from './App';
+
 import './index.css';
+import './App.css';
 
 ReactDOM.render(
   <App />,
diff --git a/template/src/logo.svg b/template/src/client/logo.svg
similarity index 100%
rename from template/src/logo.svg
rename to template/src/client/logo.svg
diff --git a/template/src/server/server.js b/template/src/server/server.js
new file mode 100644
index 00000000000..10ee4849295
--- /dev/null
+++ b/template/src/server/server.js
@@ -0,0 +1,23 @@
+import express from 'express';
+import React from 'react';
+import { renderToString } from 'react-dom/server';
+import fs from 'fs';
+
+import App from '../client/App.js';
+import template from './template.js';
+
+const isDevelopment = () => process.env.NODE_ENV === 'development';
+
+const config = !isDevelopment() ? JSON.parse(fs.readFileSync('./build/client/stats.json', { encoding: 'utf8' })) : null;
+
+const jsPath = config ? config.main.find(fileName => fileName.endsWith('.js')) : '/bundle.js';
+const cssPath = config ? config.main.find(fileName => fileName.endsWith('.css')) : null;
+
+const server = express();
+server.use('/', express.static('build/client'));
+server.get('*', (req, res) => res
+  .send(template(renderToString(<App />), jsPath, cssPath)));
+
+const port = process.env.NODE_ENV === 'development' ? 3001 : 3000;
+server.listen(port);
+
diff --git a/template/index.html b/template/src/server/template.js
similarity index 57%
rename from template/index.html
rename to template/src/server/template.js
index 72e10e94c6c..8f36fcc5b0e 100644
--- a/template/index.html
+++ b/template/src/server/template.js
@@ -1,12 +1,14 @@
+export default (content, jsPath, cssPath) => `
 <!doctype html>
 <html lang="en">
   <head>
     <meta charset="utf-8">
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <title>React App</title>
+    ${cssPath ? `<link rel="stylesheet" type="text/css" href="${cssPath}" />` : ''}
   </head>
   <body>
-    <div id="root"></div>
+    <div id="root">${content}</div>
     <!--
       This HTML file is a template.
       If you open it directly in the browser, you will see an empty page.
@@ -14,8 +16,10 @@
       You can add webfonts, meta tags, or analytics to this file.
       The build step will place the bundled scripts into the <body> tag.
 
-      To begin the development, run `npm start` in this folder.
-      To create a production bundle, use `npm run build`.
+      To begin the development, run \`npm start\` in this folder.
+      To create a production bundle, use \`npm run build\`.
     -->
+    <script type="text/javascript" src="${jsPath}"></script>
   </body>
 </html>
+`;