diff --git a/packages/flutter_tools/lib/src/commands/create.dart b/packages/flutter_tools/lib/src/commands/create.dart
index 8bf228289ce067d24eff3a047d5b3493fccff02a..3428caa438f0de0e4bc4da1dcff3080765eddcb2 100644
--- a/packages/flutter_tools/lib/src/commands/create.dart
+++ b/packages/flutter_tools/lib/src/commands/create.dart
@@ -13,6 +13,7 @@ import '../android/android.dart' as android;
 import '../artifacts.dart';
 import '../base/globals.dart';
 import '../base/process.dart';
+import 'ios.dart';
 
 class CreateCommand extends Command {
   final String name = 'create';
@@ -108,7 +109,7 @@ abstract class Template {
   final String name;
   final String description;
 
-  Map<String, String> files = {};
+  Map<String, String> files = <String, String>{};
 
   Template(this.name, this.description);
 
@@ -119,9 +120,11 @@ abstract class Template {
     dir.createSync(recursive: true);
 
     String relativeFlutterPackagePath = path.relative(flutterPackagePath, from: dirPath);
+    Iterable<String> paths = files.keys.toList()..sort();
 
-    files.forEach((String filePath, String contents) {
-      Map m = {
+    for (String filePath in paths) {
+      String contents = files[filePath];
+      Map m = <String, String>{
         'projectName': projectName,
         'description': description,
         'flutterPackagePath': relativeFlutterPackagePath
@@ -129,10 +132,10 @@ abstract class Template {
       contents = mustache.render(contents, m);
       filePath = filePath.replaceAll('/', Platform.pathSeparator);
       File file = new File(path.join(dir.path, filePath));
-      file.parent.createSync();
+      file.parent.createSync(recursive: true);
       file.writeAsStringSync(contents);
       printStatus('  ${file.path}');
-    });
+    }
   }
 
   String toString() => name;
@@ -145,8 +148,15 @@ class FlutterSimpleTemplate extends Template {
     files['flutter.yaml'] = _flutterYaml;
     files['pubspec.yaml'] = _pubspec;
     files['README.md'] = _readme;
-    files['android/AndroidManifest.xml'] = _apkManifest;
     files['lib/main.dart'] = _libMain;
+
+    // Android files.
+    files['android/AndroidManifest.xml'] = _apkManifest;
+    // Create a file here, so we create the directory for the user and it gets committed with git.
+    files['android/res/README.md'] = _androidResReadme;
+
+    // iOS files.
+    files.addAll(iosTemplateFiles);
   }
 }
 
@@ -161,7 +171,7 @@ String _normalizeProjectName(String name) {
 const String _analysis_options = r'''
 analyzer:
   exclude:
-    - 'ios/build/**'
+    - 'ios/.generated/**'
 ''';
 
 const String _gitignore = r'''
@@ -171,6 +181,7 @@ const String _gitignore = r'''
 .packages
 .pub/
 build/
+ios/.generated/
 packages
 pubspec.lock
 ''';
@@ -273,3 +284,7 @@ final String _apkManifest = '''
     </application>
 </manifest>
 ''';
+
+final String _androidResReadme = '''
+Place Android resources here (http://developer.android.com/guide/topics/resources/overview.html).
+''';
diff --git a/packages/flutter_tools/lib/src/commands/ios.dart b/packages/flutter_tools/lib/src/commands/ios.dart
index 64e64cd654bb8ff552bb31e1e01e381b5db3fa89..4345dffe827fe03c90b2b4bb32b6949e7c28ad40 100644
--- a/packages/flutter_tools/lib/src/commands/ios.dart
+++ b/packages/flutter_tools/lib/src/commands/ios.dart
@@ -13,6 +13,13 @@ import "../base/process.dart";
 import "../runner/flutter_command.dart";
 import "../runner/flutter_command_runner.dart";
 
+/// A map from file path to file contents.
+final Map<String, String> iosTemplateFiles = <String, String>{
+  'ios/Info.plist': _infoPlistInitialContents,
+  'ios/LaunchScreen.storyboard': _launchScreenInitialContents,
+  'ios/Assets.xcassets/AppIcon.appiconset/Contents.json': _iconAssetInitialContents
+};
+
 class IOSCommand extends FlutterCommand {
   final String name = "ios";
   final String description = "Commands for creating and updating Flutter iOS projects.";
@@ -93,46 +100,23 @@ class IOSCommand extends FlutterCommand {
     return true;
   }
 
-
   void _writeUserEditableFilesIfNecessary(String directory) {
-    printStatus("Checking if user editable files need updates");
-
-    // Step 1: Check if the Info.plist exists and write one if not
-    File infoPlist = new File(path.join(directory, "Info.plist"));
-    if (!infoPlist.existsSync()) {
-      printStatus("Did not find an existing Info.plist. Creating one.");
-      infoPlist.writeAsStringSync(_infoPlistInitialContents);
-    } else {
-      printStatus("Info.plist present. Using existing.");
-    }
-
-    // Step 2: Check if the LaunchScreen.storyboard exists and write one if not
-    File launchScreen = new File(path.join(directory, "LaunchScreen.storyboard"));
-    if (!launchScreen.existsSync()) {
-      printStatus("Did not find an existing LaunchScreen.storyboard. Creating one.");
-      launchScreen.writeAsStringSync(_launchScreenInitialContents);
-    } else {
-      printStatus("LaunchScreen.storyboard present. Using existing.");
-    }
+    iosTemplateFiles.forEach((String filePath, String contents) {
+      File file = new File(filePath);
 
-    // Step 3: Check if the Assets.xcassets exists and write one if not
-    Directory xcassets = new Directory(path.join(directory, "Assets.xcassets"));
-    if (!xcassets.existsSync()) {
-      printStatus("Did not find an existing Assets.xcassets. Creating one.");
-      Directory iconsAssetsDir = new Directory(path.join(xcassets.path, "AppIcon.appiconset"));
-      iconsAssetsDir.createSync(recursive: true);
-      File iconContents = new File(path.join(iconsAssetsDir.path, "Contents.json"));
-      iconContents.writeAsStringSync(_iconAssetInitialContents);
-    } else {
-      printStatus("Assets.xcassets present. Using existing.");
-    }
+      if (!file.existsSync()) {
+        file.parent.createSync(recursive: true);
+        file.writeAsStringSync(contents);
+        printStatus('Created $filePath.');
+      }
+    });
   }
 
   void _setupXcodeProjXcconfig(String filePath) {
     StringBuffer localsBuffer = new StringBuffer();
 
     localsBuffer.writeln("// Generated. Do not edit or check into version control!");
-    localsBuffer.writeln("// Recreate using `flutter ios`.");
+    localsBuffer.writeln("// Recreate using `flutter ios --init`.");
 
     String flutterRoot = path.normalize(Platform.environment[kFlutterRootEnvironmentVariableName]);
     localsBuffer.writeln("FLUTTER_ROOT=$flutterRoot");
@@ -167,27 +151,19 @@ class IOSCommand extends FlutterCommand {
       return 1;
     }
 
-    // Step 3: The generated project should NOT be checked into the users
-    //         version control system. Be nice and write a gitignore for them if
-    //         one does not exist.
-    File generatedGitignore = new File(path.join(iosFilesPath, ".gitignore"));
-    if (!generatedGitignore.existsSync()) {
-      generatedGitignore.writeAsStringSync(".generated/\n");
-    }
-
-    // Step 4: Setup default user editable files if this is the first run of
+    // Step 3: Setup default user editable files if this is the first run of
     //         the init command.
     _writeUserEditableFilesIfNecessary(iosFilesPath);
 
-    // Step 5: Populate the Local.xcconfig with project specific paths
+    // Step 4: Populate the Local.xcconfig with project specific paths
     _setupXcodeProjXcconfig(path.join(xcodeprojPath, "Local.xcconfig"));
 
-    // Step 6: Write the REVISION file
+    // Step 5: Write the REVISION file
     File revisionFile = new File(path.join(xcodeprojPath, "REVISION"));
     revisionFile.createSync();
     revisionFile.writeAsStringSync(ArtifactStore.engineRevision);
 
-    // Step 7: Tell the user the location of the generated project.
+    // Step 6: Tell the user the location of the generated project.
     printStatus("An Xcode project has been placed in 'ios/'.");
     printStatus("You may edit it to modify iOS specific configuration.");
     return 0;