Repository: Shopify/themekit
Pull request #587 (2018-10-12 14:54:14)

New command again

### Warn Checklist
- [ ] This changes the interface and requires a Major/Minor version change.
- [ ] I have :tophat:'d these changes by using the commands I changed by hand.
- [ ] I have added a dependancy to the project.



Patch:
diff --git a/Makefile b/Makefile
index ea4f1f9..25262a4 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
 .PHONY: build
-install: ## Build and install the theme binary
+install: bundle ## Build and install the theme binary
 	@go install github.com/Shopify/themekit/cmd/theme;
 lint: # Lint all packages
 ifeq ("$(shell which golint 2>/dev/null)","")
@@ -10,7 +10,7 @@ test: lint ## lint and test the code
 	@go test -race -cover -covermode=atomic ./...
 clean: ## Remove all temporary build artifacts
 	@rm -rf build && echo "project cleaned";
-all: clean ## will build a binary for all platforms
+all: clean bundle ## will build a binary for all platforms
 	@export GOOS=windows GOARCH=386 EXT=.exe; $(MAKE) build;
 	@export GOOS=windows GOARCH=amd64 EXT=.exe; $(MAKE) build;
 	@export GOOS=darwin GOARCH=386; $(MAKE) build;
@@ -27,6 +27,8 @@ build:
 			-o build/dist/${GOOS}-${GOARCH}/theme${EXT} \
 			github.com/Shopify/themekit/cmd/theme && \
 		echo "[${GOOS}-${GOARCH}] build complete";
+bundle:
+	@go run src/static/cmd/bundle.go
 sha: ## Generate sha256 for a darwin build for usage with homebrew
 	@shasum -a 256 ./build/dist/darwin-amd64/theme
 md5s: ## Generate md5 sums for all builds
@@ -39,7 +41,7 @@ md5s: ## Generate md5 sums for all builds
 	@echo "freebsdamd64sum: $(shell md5 -q ./build/dist/freebsd-amd64/theme)"
 serve_docs: ## Start the dev server for the jekyll static site serving the theme kit docs.
 ifeq ("$(shell which jekyll 2>/dev/null)","")
-	gem install jekyll
+	@gem install jekyll
 endif
 	@cd docs && jekyll serve
 help:
diff --git a/changelog.txt b/changelog.txt
index 4dc9c1c..e68dd53 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,5 +1,6 @@
-v0.8.2
+v1.0.0
 ======================
+- Changed how the New command works. Now will create files locally and upload them.
 - Fixed a problem with uploading compiled assets
 - Decoupled config file from command execution so any command can run without
 	a config file.
diff --git a/cmd/new.go b/cmd/new.go
index aa83501..ebb6b2c 100644
--- a/cmd/new.go
+++ b/cmd/new.go
@@ -2,40 +2,15 @@ package cmd
 
 import (
 	"fmt"
-	"strings"
-	"time"
 
 	"github.com/spf13/cobra"
 
+	_ "github.com/Shopify/themekit/cmd/static" // This will import the asset bundle
 	"github.com/Shopify/themekit/src/cmdutil"
 	"github.com/Shopify/themekit/src/colors"
-	"github.com/Shopify/themekit/src/timber"
+	"github.com/Shopify/themekit/src/static"
 )
 
-var bootstrapCmd = &cobra.Command{
-	Use:   "bootstrap",
-	Short: "Bootstrap will create theme using Shopify Timber",
-	Long: `Bootstrap will download the latest release of Timber,
- The most popular theme on Shopify. New will also setup
- your config file and create a new theme id for you.
-
-	Deprecation Notice: This command is deprecated in v0.8.0 and will be removed in
-	v1.0.0. Please use the 'new' command instead.
-
- For more documentation please see http://shopify.github.io/themekit/commands/#bootstrap
-  `,
-	RunE: func(cmd *cobra.Command, args []string) error {
-		return cmdutil.ForDefaultClient(flags, args, func(ctx *cmdutil.Ctx) error {
-			ctx.Log.Printf("[%s] bootstrap has been deprecated please use `new` instead", colors.Yellow("WARN"))
-			name, url, err := getNewThemeDetails(flags, timber.GetVersionPath)
-			if err != nil {
-				return err
-			}
-			return newTheme(ctx, name, url)
-		})
-	},
-}
-
 var newCmd = &cobra.Command{
 	Use:   "new",
 	Short: "New will create theme using Shopify Timber",
@@ -47,60 +22,27 @@ var newCmd = &cobra.Command{
   `,
 	RunE: func(cmd *cobra.Command, args []string) error {
 		return cmdutil.ForDefaultClient(flags, args, func(ctx *cmdutil.Ctx) error {
-			name, url, err := getNewThemeDetails(flags, timber.GetVersionPath)
-			if err != nil {
-				return err
-			}
-			return newTheme(ctx, name, url)
+			return newTheme(ctx, static.Unbundle)
 		})
 	},
 }
 
-func newTheme(ctx *cmdutil.Ctx, name, url string) error {
-	ctx.Log.Printf("[%s] creating new theme \"%s\" from %s", colors.Yellow(ctx.Env.Domain), colors.Yellow(name), colors.Yellow(url))
-
-	theme, err := ctx.Client.CreateNewTheme(name, url)
+func newTheme(ctx *cmdutil.Ctx, generate func(ctx *cmdutil.Ctx) error) error {
+	theme, err := ctx.Client.CreateNewTheme(ctx.Flags.Name)
 	if err != nil {
 		return err
 	}
+	ctx.Log.Printf("[%s] theme created", colors.Yellow(ctx.Env.Domain))
 
-	ctx.Log.Printf("[%s] created theme", colors.Yellow(ctx.Env.Domain))
-
-	ctx.Flags.ThemeID = fmt.Sprintf("%v", theme.ID)
+	ctx.Env.ThemeID = fmt.Sprintf("%v", theme.ID)
 	if err := createConfig(ctx); err != nil {
 		return err
 	}
+	ctx.Log.Printf("[%s] config created", colors.Yellow(ctx.Env.Domain))
 
-	ctx.Log.Printf("[%s] created config", colors.Yellow(ctx.Env.Domain))
-
-	for {
-		if theme, err := ctx.Client.GetInfo(); err != nil {
-			ctx.Err("Encountered an error while checking new theme. Please run `theme download` to complete the setup.")
-			return err
-		} else if theme.Previewable {
-			ctx.Log.Println("downloading...")
-			break
-		}
-		ctx.Log.Println("processing...")
-		time.Sleep(500 * time.Millisecond)
-	}
-
-	return download(ctx)
-}
-
-func getNewThemeDetails(flags cmdutil.Flags, getVer func(string) (string, error)) (name, url string, err error) {
-	name, url = flags.Name, flags.URL
-
-	if name == "" && url != "" {
-		parts := strings.Split(flags.URL, "/")
-		name = flags.Prefix + strings.Replace(parts[len(parts)-1], ".zip", "", 1)
-	} else if name == "" {
-		name = flags.Prefix + "Timber-" + flags.Version
-	}
-
-	if url == "" {
-		url, err = getVer(flags.Version)
+	if err := generate(ctx); err != nil {
+		return err
 	}
 
-	return name, url, err
+	return deploy(ctx)
 }
diff --git a/cmd/static/generated-assets.go b/cmd/static/generated-assets.go
new file mode 100644
index 0000000..813b81c
--- /dev/null
+++ b/cmd/static/generated-assets.go
@@ -0,0 +1,7 @@
+package static
+
+import "github.com/Shopify/themekit/src/static"
+
+func init() {
+	static.Register("PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1b\x00\x00\x00assets/application.css.scss\xd2\xd7W((-Q\xa8\xcc/-R(.\xa9\xccI-V\xc8H-J\xe5\x02\x04\x00\x00\xff\xffPK\x07\x08\xd8Y\x83\x98\x1e\x00\x00\x00\x18\x00\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15\x00\x00\x00assets/application.js\xd2\xd7W\x08(-Q\xa8\xcc/-RH,(\xc8\xc9LN\xcc,\xc9\xcfS\xc8J,K,N.\xca,(Q\xc8H-J\xe5\x02\x04\x00\x00\xff\xffPK\x07\x08\x11\xad\xdd#.\x00\x00\x00(\x00\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19\x00\x00\x00config/settings_data.json\xaa\xe6RPPJ.-*J\xcd+Q\xb2RPrIMK,\xcd)Q\xd2\x01\x89\x17\x14\xa5\x16\xa7\x96\x14+Y)\x80\x94) d\xad\x14\xaa\x15j\xb9\x14\x14j\xb9j\xb9\x00\x01\x00\x00\xff\xffPK\x07\x08s\x98U8<\x00\x00\x00B\x00\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1b\x00\x00\x00config/settings_schema.json\x94\xce\xc1\x0e\xc2 \x0c\x06\xe0;O\xd1p6c^\xf7\x1az3f\xc1\xd9I\xe3\xa0\x04\x8a\x891\xbe\xbb\xc1\xcd\x03G\x8f\xed\xf7\xffMO\n\xe0\xa5\x00\x00t\xb0\x1e\xf5\x00Z\x1cz\x1c)\xcc\xacw\xab\xac\x9b\x9f\x1f\xebt'\x01A\x1f\x17+\x08_o\xc3\x0fL\x998\xd4\xfc\xbe\xeb\xbb\xbeU[\xc4q\xaaxp\x1ci~\xb6|\xe5\xa9x\x0cb\x858\x8c%-5\xe9Db\x1e\x8c\xb9\x91\xb8r\xe9&\xf6f+\x1b\xd9>j\xaf\xe4\x12#'\xf9\xa3o(\xe7\x82Y+\x80\xb7:\xabO\x00\x00\x00\xff\xffPK\x07\x08\x8e\x0b\x84\xc8\x97\x00\x00\x00\x1c\x01\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x13\x00\x00\x00layout/theme.liquid\xa4T\xcd\x8e\x9b0\x10\xbe\xe7)f\x91\xa2\\\x96D{\xeb\x01\x90\xaa\xaaR\xfb\x00\x95*\xadV\xc81\x13\x98\xc6\xd8\xd4\x1ev\x95&\xbc{e\x1b\x08\xd9lO\xbd\x80g<\xdf\xf7\xcd\x8f\xed\xec\xa12\x92O\x1dB\xc3\xad*VY\x83\xa2*V\x00\x19\x13+,\xceg\xe8D\x8de\xb0`\x18\xb2]\xf4\xfb\x88\x16Y\x80l\x84u\xc8y\xd2\xf3!\xfd\x94\\7\x1a\xe6.\xc5\xdf=\xbd\xe6\xc9\xcf\xf4\xc7\xe7\xf4\x8bi;\xc1\xb4W\x98\x804\x9aQs\x9e|\xff\x9acU\xe3\xa3l\xaci1\x7fZ\x10h\xd1b\x9eT\xe8\xa4\xa5\x8e\xc9\xe8\x05lJk\xb1\x0b\x17@'E\xe7\xb3\x8c,\x8a\xf4\x11,\xaa<\x91B\x1bMR\xa8\x04\x1a\x8b\x87\x80\x9f}eo\xd5\x8cY(\xbf\x12\xbeu\xc6\xf2B\xf6\x8d*n\xf2\n_Ib\x1a\x8cG\xd2\xc4$T\xea\xa4P\x98?=\xba\xc6\x92>\xa6l\xd2\x03q\xaeM\xa0\xf5r\x91\xa3<\x18[\xfa\x1e\xa3\x85a\x80\xec!M\xe1[4\x1bc\x8ep0\x16:\xd5\xd7\xa4\x1d\xa4\xe9\x88\xdd\x88\xaeS$\x85/s\xeb\xa4s[\xe9\xdc\x06. \x9cC\x0e\xf9_\xc0\xf1I\xa1k\x10\xb9dQ\xc30|\x80\xfdu\x8f\n\xed\x9b\x10\xd9.\x8e?\xdb\x9b\xeaT\xac<\xc3:\xa4\x14ZI:\xfc\x159v\xdbV\x90N[\xd4\xfd\xd6\xfb\x1c\xac\xbd^\x88\x17\xceQ\xadA6\xa4\xaa\xd2\x07\x97\x8d\xd0\x95B\xc8\x03|\x1b\x8f\xd2\x05\xa2\x97\xfe\xe0\x02K\x87\xab\xc4\xf3\x1d\xc3\xcb\xa8\xf5\x90\xc3^	}\x9c\x80\x00\x99\xb8\x0e6\x88L3\x9d\xec\xeb\xf9\x15\xc5\x88y\x1ek\x0b2w\x05\xfe[}\x16\xbd\x95\x9di\x96\xdaW\xe7T\xf5|F\x17\x99\x9c\xd7\x80\xba\xf2\xb9\xac\x87\x97\xa9\x15\xa8\x1c\xfeO\x81\x91\x94\x0e\x91c)\xe1\xe7:\xf3\xed\xa4\xb0\x9c\x14\xfe\x1b\xa0\xabi\x0e\xae1\xddV\xf6\x8eM\x8b\xb6\x14R\x9a^\xb3+Q\x8b\xbd\xc2\xeavfS\xd8\x07\xf9\xeeFdR\x8c\x8be\xddg\xd8(S\x83\xe9y\x03p\x99iJej\xd3s\x19\x862\x0c\x1fwd\x02\x93\x86\xcd;,\xe9\x1bh\x8c\xb5X\x93c\xb47\xc1\x93\xf3N\xea}\xe7\xa2\x15^\x08A\x1a\xacQ\x98'~\x99\x8c\xdd\xbe\xbd\xe1J\x9cL\xcf\x910\xdb\xf9\xb8b\x95\xed\xe2\xad\xcav\xf1\xa9\xfd\x1b\x00\x00\xff\xffPK\x07\x08b#~rO\x02\x00\x00{\x05\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17\x00\x00\x00locales/en.default.json<\xcc\xb1\n\xc20\x14\x85\xe1=Oq\xb8\xb3\x83C\xa7>\x84\x93\xbbTz\x9a\x06\xe3\xbd\x92\xdc`E\xfa\xee\x12A\x873\xfc\x1c\xf8\xde\x01\x90He\x99\xb2\x8c\xe8	\xc8p\x1c\xfe\x01\x88'\xcf\x94\x11r2\xc7bMg9\xfc\xbe\xda\xae\xce\xcd/\xab\xdf; \xe7\x95xL\x91xY\xc3\x93\x85\xc8f\xb7\xa4\x11\x8b\x15\xcc\xc6\n5\x07\xb7T]\xbe\xc8\x1e\xfa\xf6\xf0	\x00\x00\xff\xffPK\x07\x08\xe5\xb4\xaacr\x00\x00\x00\x8b\x00\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x00\x00\x00templates/404.liquid\xb2\xc90\xb4\xab\xaeVPOO\xcdK-J\xcc\xd1310\xd1+\xc9,\xc9IUW\xa8Q(Q\xa8\xad\xb5\xd1\xcf0\xb4\xe3\xb2)\xc0PU\\\x9aT\x92ZQ\x12\x9fQ\x92\x9b\x83P\\`\xc7\x05\x08\x00\x00\xff\xffPK\x07\x08\xdc\xdb\xd3\x0fB\x00\x00\x00S\x00\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00\x00\x00templates/article.liquid\xa4T\xddn\x9c<\x10\xbd\xcfS\x8c,\xa1\xbd\xf9\xb2Q\"}7\x11\xd0?\xf5!\xaa\xaaB\x06\x0f\x8b%l#\xdb$\xdd\x12\xde\xbd\xf2\x1f\xb0\xec6\xbd\xe8\x15\xf6\xf8x\xe6\x9c3\x83\xa7\x0c\xa81\xfc$A\x8e\xa2F]\xa9\xb6j\x94\x10(\xad\x81\x02\xa8\xb6\xbc\xe9\xf1\x98BU\xa3Fi!\x9b\xef\xa6\x0cx\x0b1\x0eT\xb2\xb4>6\x1a\xa9EVQ\x8f\x03\xf8\x97\x12(\x19o\xdd\xfa.\xef\x1e\xcbiZ\xd0\x96\xdb\x1ea\x9e\xf3\x87\xee\xb1t\xc8\x86\x0ev\xd4\x08t\xb4\x9d\xd2\x90\xcd\xb9\xb1Z\xc9\xd3\xf6R<s\xb7\xd2\xa1/\x91\xee\x86\x9ai\xc7\xa8u\xa1\xdcr\x116nQ\x90M\xbea\xac{n\xba\xa0\xf5\xcdc\x9e\xe1\x90}\xbb\xcf\xc4}\xc6\x0e0\xcf\xa4\xfc\x1b\xbcUZP\xfb\x0c\x07\xa1\xa4\xed*F\xcf\xd5\x19\xa9>x\x96\xae\xe2\x0d\x8e7\x14\xc1G\xd8\x847-\x98\x9dw\x8c\xbfl\x894JZ\xd75W\xc2\x1d\xc5f\xd6\xbd:\xadm@I\xeb\x1e\xd9\x87\xd0\xc4\xbc{r\x19ntp\x9eS\xe7M\xfe\xd0=\x95\xa1\xe3\x03=q\xe9\x0c\xdc\xb7\x17\xea3\xfc\x1frz`\xab\xf42E\\^\xc3#\x12\xc0\x8b\x88\xeb\xb8\x9b\xa6u\xe8\xf6\x92\x12p\x83\xd9\x99uc^\xe7\xa5\xd8\x9a$\xd8\xdf\xfa\x99J\x01\xde.\x02\x8f\x03=\xa1\x81\x12\x1eW\xaa\xd3\xb4\xea\x7f\x03\x86-\x1d{[\xc5\x10W2\xd5\xd9\x0ex\xda-\x17\xdd\xd0oU\x07\xaf\x04\x1c$\xbe&\xf7\x0f\xff%\xc3.\x8a;\xdc\x11\xb5V\xdal\xea\xc7\xc0\xaa\xb1\xa75\xf6\x0e\\\x90/!\xdf'\xef\x10)%\x15\x98?\xf8\xf3\xe4d\xce\xe50Z\xb0\xe7\x01\x0bb\xf1\xa7%\xe0P\x05\x89T\xbe\x07w\x7f\x10\xe0l\x9f\x0f\x86\x9e6\xd8\xa9\x9e\xa1.\x88\xbbF\xe0\x85\xf6c\xf8\x9b<\xdb\xa57\xc4\xfd\xc1\xaa\xa1\x03\xb7\xb4\xe7\xbf\xb0 \xafJ3C\xca\xbb?\xd3\xfe*(\xefI\x89\xee\xf3\x1em\x0f\xd8\xf3\xf6\xc1K\xda!\xdf%\xebxwG\xdbGW\xd6JkllAT\xdb^\xebp\xc1\xf7T|V\xecLJ\x81\xc6\xd0\xd3\x95\xfb\xceq\xaa\x91\xee\xc8\xd7\x8a\x9d/\xb9\xfb,\x97\xd4cJ\xff\x16y\xd6\xeeVx_b\xd6\x95\xd6\xd6.3\xd6\x82\xdbE\xf3\xa0\x8c%\xbb\x7fB\xc4\xd7ayF\x96y\xfe\x1d\x00\x00\xff\xffPK\x07\x08\xeed\xcdfN\x02\x00\x00Y\x06\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15\x00\x00\x00templates/blog.liquid\\QK\x8e\xeb \x10\xdc\xfb\x14\xa5H\xde:q\xa4\xb7yb\xd0\xdc$\"v; 1\xd8\x82\xf6\xfc\x08w\x1f%\xe0\x04egw\xd7\xaf\xa9\xd8bQ\x17\xe3\x14\x13\xcev\xbet\xca\xb3\x19,\x05\x9c\x7f\xf0\x0fmj\x1a\xa1{\x19c\xde\xb2aKHI\xecu/\x9b\xd8b\x9a=\n\x05\xc6\xbdH\xb4\xa9\x01\xc4h>e\x03\x00B\x1f\xa5P\xd0\x9e\xa6\xb7]\x8c\x1b\xaf[\xbdEJ;Y\x8d\x9e>J\x8a\xbd>f\x81\n\xa0V\xd6\xb3GJx\xaf\xc7\x83'\xc54\x9e\x14#\xa5l\xfa\xb0\x07b\x0b3=\xb0\xf4=\x90_\xb8\x0b\xe6\x97 q\xc8q\x0b2\xbe\xc26\xbd\xbb\n\xd9@5\\,u\xf8avL\x8eqE`o\x96\x93\xe6\x0f\x8b+\xd8\xafnPL_\xb3\x1f\xc3\x7f\xf4\x87\xc3\xfd\xc0\xa5JGn4\xd3&,\xf6%z\xf9\xc8\xfb\xdb\x83\xdfZ\xc9\xb7l\xddu\x8b\xbaP\x80D\x9f\xd91>k\xbdb\xa4I\xad\x96Oedfw\xbb\xa6\xf6+?\x0fN\x9b\x9a\xbf\x00\x00\x00\xff\xffPK\x07\x08\xe3fQG\x0b\x01\x00\x00\x1a\x02\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15\x00\x00\x00templates/cart.liquid\x8cTMo\xdb<\x0c\xbe\xf7W\xf0\x15\x90\xb7\xb7\xa8\xed\xb1\x93\xbdC\xff@w\xd8i\x18\x02\xc5Rb\xa2\xfa\xf0$*[\x90\xfa\xbf\x0f\x92\xe3\xd8\xf9\x18\x90\x93MJ\x0f\xc9\xe7\x11\xc9\xc3\x02p\x03\x8d\x0c\xb4D\xd2v\xd5\xf8\xe4\x08jx\x82E\xff\x00 \xda\xe7:\x1f\n\xde>\xd7\xd9\xde\xf8`A6\x84\xdeU\x8c\xe7#\x06VS\xebU\xc5:\x1f\x89\x81\xf3;iPI\xd2\x19\x00 H\xae\xcd\xf1?[\xad\x96j\xb4\x8a\x0d\x8d7\xb1\x93\xaeb/\xac~\x0f^	N\xed\xd9\x8d\xfa=`\xa3\xaf\xdd\xdfh\x7f\xed$O\xd2\xcc\xdd\xf9\x7f\x96S\xd0\xda\xab\xfd\x849,`\xe3\x03d\xf6\x80n\x92\"\x0e\nL\xa1C=3\xb3C\x9d;\x00\x84\x846\xe8M\xc5\x0e\x87\x12o\x99\x82\x81O\xf8\x8d\xd4\xa2{\xcd<\x8d.\xd2\xc5\xa54\x06\xfa\x9e]F\x00\x10h\xb7\x10Cs\n\x02\x9f\x80v\xbbJ\xc1\xbc\xc2\xa3\xd5\n\x93}\xccP\x90\x86\xa6L\x84d4|\x82\x8e\x8d\xec\xf4\xad\xd0\x82\xcb\x0b\x02\xfc\x92\xc1\xbd\x94r\xf4\xd1\xee\x82W\xa9\xa1c\x01}\x7f\x95\x06`\xbc\xba\x93\x01\xa5\x9b\xae\xfe+Ui+\xde\xb4\xd2m\xf5W\x83NW\x87C~#\xe3}\xb7D\xa7\xf4\x1f\xe8\xfb\xff\xa5\xed\xbe\xfcJ\xd2\x11\xd2\xbezbu\xd0\xd6\xef\xf4\x9d,\xa7\xea\xb1\xc9\xb2Y\xef\xf4\xbeT\x7f\x8f&\xe8\xbaD@\xfbNW\xcc%\xbb\xd6\x81\x81\x93VW,u\xb9\xf1\xe3\x8f\x9f\x0cP\x9d\xcc\xd5\x98\xee\xa3$a\xb0\x93&\xe9I\xd3\x91F9\xb3\xe8*\xf6\xc4\xeeaq\xa9s\x99\xe5\x12\xd1\x07\xdc\xa2\x93f\x95\xe5[\x0d,\xff\xab\x86\xb3\x99k\xd1\x8f%\xdc\x02L\xb2\x1c\x16\xa0\x9d\xc2\xcd\xf9H\xc0\xecmo\xc2\xae\xeb\xcb\x93\xa60\x0e[\x06\xdd\x80\x1d\x1dq\xa8g4O}2d\xcf\xd0\x8b\xf4\x97\xaa\x08>\x1f\xd2\x1b0\xc1g\xc3/\xf8l3	\x85\xbb\xd3\x86\xe8\xea\x98\xd6P\x16	\xbcf\x8ae)\x14\xfb\x8a\xa3\xe0\xdd	\xb7ND\xde\x1d\x1b#\xa6\xb5E:o\x0cV\x7f/_\xc1\x87\xab\xf7 \x9bV7\x1f>\x11\xab\xdf\x8e\x7f\xe7h\xc1\x8f\xa5\x0b\x9e\x97s\xfd\x90y\x9b\xa8\xc7\x05\xfe2.\xf0\x97|\xe9M\x06\x02\x8c\xa0mG\xfb\x87\xf9\xbb\xfe\x0d\x00\x00\xff\xffPK\x07\x080\xb7G0C\x02\x00\x00\n\x06\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1b\x00\x00\x00templates/collection.liquid\x9c\x92\xcd\xaa\xdb0\x10\x85\xf7y\x8aC@dg\x93.\x83\xaaW	\x13yl\x0bd\xc9HrJ\x90\xf5\xee\xc5\x89\xed\xbap\xb9\x8b\xbb\x1bF\xe7;\x9a\xbf,0Rg\x1c%\x86\xf6\xd6\xb2N\xc6\xbbj\x0c\xbe\x99t\x8ax\xbc\xf0\x0b\xa2\x9c\x00\xd9_U\xceGQ2\xc92J\x91u\x7fU' \x0b\xb4>`ea\xdc\x97\x8eo3@6\xe6\xa9\xde\x11 	}\xe0\xf6\xf79\xe7\x8d\xae\xa6`1\xe3\x8fI\xbdq\xb7\x83\x11J9\xab\x83\xee_\x11\xb4\xd9\x1d^\xc7`4c\xc6\xe0\x1d\xbfP\xca\xa6\x10\x98\x9c\xe5\x18w!=\xc9XzX\x86(\xf2\x11\x94\x8c)x\xd7\xa9\xe8m\x03?%Y\xaf\x89,\xc0\xaeYiQ~\xda\xc1\xca\x01\xd2\x0c\x1db\xd0\xff\xa1-S\x9a\x027w3P\xc7U\x0c\x1a3\xcc\xd0\xdd\xa7`o\xb8X\n\x1d_\x16\x1f\x90M\xdf\x91d\x13fp\xd44\xf2\xf1\xdf}Z\xb2^\xf7\xb0\xf4e#\xef\xeb\x19\x95\xf3\x18(\xe9\x9e\xa3\xac\xc7M\xe2\x9ae\xc5oQ\x160\xed~=\xd5H\x1dG(\\7\x8b\xa5\xaa\xed\xb4f4\xdc\xd2d\xd3}M}\xe6\xb0\x9b\x9av\xa1>\xf1\x0e\x89r\xfa\x1b\x00\x00\xff\xffPK\x07\x08\xe1\x0c\x17n3\x01\x00\x00\x9f\x02\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00templates/collection.list.liquid\x9c\x92\xcd\xaa\xdb0\x10\x85\xf7~\x8a\xc3\x05\x91\x9dM\xba\x0c\xaa^%L\xe4\xb1-\x90%#\xc9)A\xd6\xbb\x17'\xb6\xebB\xe9\xe2\xee\x86\xd19\x9f\xe6/\x0bL\xd4\x1bG\x89\xa1\xbd\xb5\xac\x93\xf1\xae\x9e\x82og\x9d\"\x1e/\xfc\x80(\x15 \x87\xab\xca\xf9,J&YF)\xb2\x19\xae\xaa\x02\xb2@\xe7\x036/\x8c\xfb'\xf1\x0d\x03dk\x9e\xea\x1d\x01\x920\x04\xee~~\xe5\xbc\xbb\xeb9X,\xf8e\xd2`\xdc\xed\x04B)_\xea\xa4\xfbS\x04\xed\xb8\xd3\xeb\x14\x8cf,\x18\xbd\xe3\x17J\xd9\x15\x02\xb3\xb3\x1c\xe3!\xa4'\x19K\x0f\xcb\x10E>\x82\x921\x05\xefz\x15\xbdm\xe1\xe7$\x9b-\x91\x05\xd8\xb5\x9b[\x94\xefv\xb0\xf9\x00i\xc6\x1e1\xe8\xbf\xac\x1dS\x9a\x03\xb7w3R\xcfu\x0c\x1a\x0b\xcc\xd8\xdf\xe7`o\xb8X\n=_V\x0e\xc8\xa6\xff9\xc9&,\xe0\xa8i\xe2\xf3\xbf\xc7\xb4d\xb3\xeda\xed\xcbF>\xd63)\xe71R\xd2\x03G\xd9L\xbb\xc4\xb5\xeb\x8a\xdf\xa2,`\xba\xe3z\xea\x89z\x8eP\xb8B\x94\xb5\xa0\xfd\xaa\x16\xb4\xdc\xd1l\xd3}K}F\xf0\x81\x99ne}\xe2\xc3!JU\xfd\x0e\x00\x00\xff\xffPK\x07\x08L\xb9{)4\x01\x00\x00\x98\x02\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\"\x00\x00\x00templates/customers/account.liquid\xb2Q\xd4\xd5U\xd0/I\xcd-\xc8I,I-\xd6O.-.\xc9\xcfM-*\xd6OLN\xce/\xcd+\xd1\xcb\xc9,,\xcdLQ\xd0\xd5\xb5\xe3\x02\x04\x00\x00\xff\xffPK\x07\x08\x921\xff\xfa3\x00\x00\x00-\x00\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00+\x00\x00\x00templates/customers/activate_account.liquid\xb2Q\xd4\xd5U\xd0/I\xcd-\xc8I,I-\xd6O.-.\xc9\xcfM-*\xd6OL.\xc9,K,I\x8dOLN\xce/\xcd+\xd1\xcb\xc9,,\xcdLQ\xd0\xd5\xb5\xe3\x02\x04\x00\x00\xff\xffPK\x07\x08\xeb\xdf\xdd|<\x00\x00\x006\x00\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00$\x00\x00\x00templates/customers/addresses.liquid\xb2Q\xd4\xd5U\xd0/I\xcd-\xc8I,I-\xd6O.-.\xc9\xcfM-*\xd6OLI)J-.N-\xd6\xcb\xc9,,\xcdLQ\xd0\xd5\xb5\xe3\x02\x04\x00\x00\xff\xffPK\x07\x08\x1by!\xbf5\x00\x00\x00/\x00\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00templates/customers/login.liquid\xb2Q\xd4\xd5U\xd0/I\xcd-\xc8I,I-\xd6O.-.\xc9\xcfM-*\xd6\xcf\xc9O\xcf\xcc\xd3\xcb\xc9,,\xcdLQ\xd0\xd5\xb5\xe3\x02\x04\x00\x00\xff\xffPK\x07\x08\xe03\xbf?1\x00\x00\x00+\x00\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00templates/customers/order.liquid\xb2Q\xd4\xd5U\xd0/I\xcd-\xc8I,I-\xd6O.-.\xc9\xcfM-*\xd6\xcf/JI-\xd2\xcb\xc9,,\xcdLQ\xd0\xd5\xb5\xe3\x02\x04\x00\x00\xff\xffPK\x07\x08\xd6\xf0}\x961\x00\x00\x00+\x00\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00#\x00\x00\x00templates/customers/register.liquid\xb2Q\xd4\xd5U\xd0/I\xcd-\xc8I,I-\xd6O.-.\xc9\xcfM-*\xd6/JM\xcf,.I-\xd2\xcb\xc9,,\xcdLQ\xd0\xd5\xb5\xe3\x02\x04\x00\x00\xff\xffPK\x07\x08\x99l8\x0d4\x00\x00\x00.\x00\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00)\x00\x00\x00templates/customers/reset_password.liquid\xb2Q\xd4\xd5U\xd0/I\xcd-\xc8I,I-\xd6O.-.\xc9\xcfM-*\xd6/J-N-\x89/H,..\xcf/J\xd1\xcb\xc9,,\xcdLQ\xd0\xd5\xb5\xe3\x02\x04\x00\x00\xff\xffPK\x07\x08	\xdd\xe1\x8a:\x00\x00\x004\x00\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1a\x00\x00\x00templates/gift_card.liquidl\x93_k\xdb0\x14\xc5\xdf\xf3)\xee\x04\xa1-Dq[\xf60:)\xd0\x95>\xf4qcc{\x0b\xaa\xee\xb5\xad!K\x8e|\xe3,x\xfe\xee\xc3r\xdaf\xd07\xf9\xfe\xf9\xe9\x9c#<,\xc1\x9bc\xdc3\x84\x18\x08\x96\xe3B}\xc0h\xf9\xd8\x12\xd4\xdc\xf8\xcdB\xd5dp\xb3\x00P\x0d\xb1\x01[\x9b\xd4\x11k\xb1\xe7R~\x12o\x8d\x9a\xb9\x95\xb4\xdb\xbb^\x8b_\xf2\xc7\xbd|\x88Mk\xd8={\x12`c`\n\xac\xc5\xd3\xa3&\xache\xeb\x14\x1b\xd27g\x80`\x1a\xd2\xa2wthc\xe2\xb3\x9d\x83C\xae5R\xef,\xc9\xfc\xb1r\xc1\xb13^v\xd6\xf8\xf7(eL\x8da\x89\xc4d\xd9\xc5pFc\xf2\xd4\xd61\x90\x0e1\xef\x0d\x03\\\xf4\x140\xa6b\x97lDZ\xff\xee.\xe0/tul]y\xdc\x9a\xae#\xde\xee\x93\x9fj6\xb9\x96\xb7l*\x18\xc7\x85*\xe6l\xd4s\xc4c\x96\x80\xae\x07\x87Z\xec\x92\x9cHb\xa3\nt}n\xcd\xab\xd3\x11 \xd0\x01\xbe~{\x88H\x97\x18\xed\xbe\xa1\xc0\xeb\x8a\xf8\xd1\xd3t\xfcr|\xc2\xcbW\xc4\xd5\n\x86\xbc\x04\xc0\xf4\x87\xef@\x0c\x03T\xae\xe4\xad5	\xd7\xbb\xb4uH\x81]\xe9(\xc18\x8a\xd5i8\x07u\x077\xb7\xd7/\x95\x9a\\Us.\xe5\xcax\xf5y\x12V\xbc)Se\x8cLi\x169,\xc1\x95g7\xb5\xa6\xebr\x0c\xcb1\xf7\x95\x81:Q\xa9\xff\xd7\xf3:5\x8ebs\xbaX\xb9\xa6\xca\xb1\x98\xb6\xf5$\x0f\xc6{b\xf9l\xb0\"\x01]\xb2\x19q11\xe4\xc4(\x0c\xa2\xe4(\xcf\xa7\xd7]_\xbd\xff(\xe3(f\xafZ\xdc\xdc^\x8b\x93K->^\x0b0\x9e\xb5\xb8G\x84\xef\x11\xee'\x1a\xfc\xcc\xb4\x932U\x98W\xab\x14\xd0\x95\xb35U\xbc\xc4\xa0\x8a\xf9eU1\xff\x0b\xff\x02\x00\x00\xff\xffPK\x07\x08\xf0\x94z\xf6\xd6\x01\x00\x00.\x03\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x16\x00\x00\x00templates/index.liquid\x9c\x91\xb1n\xeb0\x0cE\xf7|\xc5E\x00![\xb2\xbc)\xd0\xf3\xaf\x04\x8aL;\x04h\xc9\xa0\xe8\x14\x85\xad\x7f/\x92\xb8\xad\xbbt\xe8*\xdes$]\xce\x0e]V\x8c\x9a\xdb)\x1a8!f\x11\x8a\xc69\x95c\xa79\xd9\x18z:\xae\x81\x02\xe1\x81\xed\xfc\x0f\xae\xee\x00\xdf\xf2\xbd\xd9\x01\x80\x0f\xb8)u\xff\xf7\xf3\xfc);N*X\xf0\xc6v\xe3t\xdexQ\xeb\xbe\xd9\xe4\x8cM\x08\xb5\xfaSx\xc96\xb3Q9\x12\x16\x0c9\xd1;j}\xcd\x1d\xa6$T\xcaW,\xdc\x03K\xb8\n\xc1U\x7f\xd5\xc6\x17\xd3\x9c\xfa\xa6di\x91'\xf3\xa7\xf5`v\xa0\xd4\xae\xb4\xab\x7f{\xfb\x93\x02<\x0f=\x8a\xc6\x1f`G\xc1&\xa5\xf6\xc2\xc3\xa3\xb7\xa2\x11\x0bx\xe8/\x93\xca\x19\x07	\xda\xd3\xe1aA\x10\xfb\x8d\x0cbX@%\x86\x91\xbeo];\xf2\xa7g\xf3\xaf\xdf<\x16\xe8\xea\xee#\x00\x00\xff\xffPK\x07\x08\xe5\xc8?\xa0\xec\x00\x00\x00\xcb\x01\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00!\x00\x00\x00templates/list-collections.liquid\x9c\x92A\xae\x9c0\x0c\x86\xf7=\x85\xf5$\xcajfV\xddL\x19n\xd03 ?b\xc0RH\xa8\x93\xbcQ\xc5\xe4\xee\x15\x10\x98\xb0\xe9\xa2;\xb0\xfd;\xfe\xfc{.\xa0\xb3\x02\xad\xd5\x9aZ\xcf\xd6\x00\x9b\xec\xcfA\x11\xbf\x01\xcc\x05\x04\xa3\xc9\xb9,u\x1d\xd0(M\xf0x@\xd9\x895~\xc2\x9e\xca\xad~U\xb48\xf9 \x94I\x1a\xcf^\x13\x14q\x9e\xf3F[\xf4\x05\xe4Z\x9c\x08b\x9c\x0b \xa3v}\xeaX!\x0cB\xdd\xe3\xe3,\x0e\xa2!\xc6\x8f\xfa\x97\x15\x82S*\xbd\x16#|\x17\x87\xbf\x83\xfdY\xdd\xb0\xde\xa7[\xa8'\xb1*\xb4\xfe\x8c|MQ\x07\x9aG\xf6\xf7\x1f\xfb\x00\xab\x0c\x9d\xe3\xde@/\xac\x1a\xf646OV~\x80\x07\x94\x1a\xa5\xa7\xcb\xc5\x1a\xbat\xdc\xf9\x01FR\x1c\xc6-2\xa0\xee\xcaw\xa3J\xf1W\x9d\xbe\xcfd\xe9\xf1\x15\xeb\x05O\xf6\x03\x9b{n\xcf\xc2\x9a\xd5\xed\x8c\x07\xda:\xe7;?	\xb7\xcbnGk\xe8\x0f\xc4\xf8\xae9,\xddK\xf1\x0bY\xe3\xe7jP\xf5)u\xe5\xbcX\xd3\xd7\xcej\x056\xf8\xea\x96\x02\x9b=I]\xc4\xff\xe78\x94\x00\x15\x8f=8iO\xe2\x8ep\xb9\x00\xd5\xf0\x88=]\x9d\xb4\xf0\x02\x1e\xfb&\x88\xbe\xa7\x8d\x97K'@\xed\xff\xa5D\xed\xf3\xfb\xca^\xce\xf6V\xdd\x0eW6\xc2\xe5D\xf6\xf3?\x01\x9f\xd2\x7f\x03\x00\x00\xff\xffPK\x07\x08\n	\xee0b\x01\x00\x00B\x03\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1d\x00\x00\x00templates/page.contact.liquid|\x92Mk\xbb@\x10\xc6\xef\xf9\x14\xc3\x80\xe4\x96\xfcs\xd7\xfd\x1fJ{k\xe9\xa1\xb7\x12\xc2\xc6\x1d\xe3\xd2}\x91}i+\xd6\xef^v5P\"\xe64\x8e\xf3<\xcf\xcf\x91)\xdb\x03\x1b\x06\xe8\xf8\x85vA\x06E0\x8e\xe5\xbe=\xb0\xcdP@c\x9d\x86mmM\xe0u\xd8B1n\x00\x86\x02d\x93'\xbb\xce\xfa@\xe2\xe4c]\x93\xf7MT\xaa\xff\x0f\xc5\x08o-7\x1f\xd0\xdb\x98d\xa9:\x983\x92\x9b\x8c\x90\xcd\x9c5LA\xe4\x9cu\x1e~@P\xc3\xa3\n\xa7\xf9\xc5\x98D\xa5\xe2gRIX\xe1\xc3\x14\xf3d\x9d~\xe1\x9a\x90\x19\xae\xa9\xdcg\x05KZi\xba\x18 \xf4\x1dU\x18\xe8; H\xb1\xb4A\xb2U8\x7f\xd4{\xea\x8e\xc8\xd6Y\x8f\x9aK\x85\x8cRY\xa3\xe5\xe1\x0279oxYz\x17\xf8\xdaZC\xc8\xbaT\xd6\xd7[\xe2&\xdf\x0d.\xa7\xdc\xc5=\x93\xf7\xfcB\xc8\xf4\xf4\xf0\x17\x99\xfe\"w\xc4\xc1\xd9/_\xe1\xe1\xdf\x02zu\xdf`\xcfV\xf4Gd\xe5\xfe\x9a\xb0\xd8\xc0\xc7\xb3\x96\x01\xe1\x93\xab\x98Z2\x02\xf3\xdd\x91\x11\xf9\xf4\x8aq\xf3\x1b\x00\x00\xff\xffPK\x07\x08\xc1t\x0b,%\x01\x00\x00\xa0\x02\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15\x00\x00\x00templates/page.liquid\xb2\xc90\xb4\xab\xaeV(HLO\xd5+\xc9,\xc9IU\xa8\xad\xb5\xd1\xcf0\xb4\xe3\xb2I\xc9,\x83K%\xe7\xe7\x95\xa4\xe6\x95\x80%A\xe2\\\x80\x00\x00\x00\xff\xffPK\x07\x08\xc9\x06\xe5\x902\x00\x00\x008\x00\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00\x00\x00templates/product.liquid\x8cSM\x8b\xdb0\x10\xbd\xfbW\x0c\x82eO\x1b\xb3\xd7\xc56,\x85Bo[\xda\xbb\x99Hr2\xa0\x0f\xaf4N	N\xfe{\x91e;\x1fMKOQ\xa47\xf3\xde\xbcy\x1e\x9f\x00c\xa4\x9d\x039\x84\xa0\x1d\xb7\x07\x0c\x84\x8e\xa1\x86>x5H\xdeDm\xb4d\xadZ\x1f\xda\x8eB\xe4\x16\x0fH\x06\xb7F\xaf\xe8\xa7sqi\xd5i\xe4!h\xd5\x92\xc5\x9d\x86\xfa\xbe\xf7\xe6\x0ep\x02\xa5;\x1c\x0c\xbf\xad\x9cw\x88\xa7sQ\x91\xddA\x0c\xb2\x16\xe3x\xcfp\x02\xb2\xbbv\x08\xe6\x0d\x9e\x0d\x86\x9d~\x86\xf3Y\x00\x1a~\x80\xde\xa0a8\x81\x8e\x12{=\xe1H\xd5\xe2#\x13\x7f\xec=\xfbov'\x9a4O\xe7\x03d\x06r\xab\xb4\xe9\"&I\x00\x15\xc2>\xe8nb\xc9\xcdc\x90\x7f\x91\xd3\x14\x00\x007c<.\x91\xde\xf6(\xf9v\x86\xc7\xd2S\xcf\xaa\xc4I\xacv*\xe9MV\xed_\x9bq\\\x053\xb1I\xe8\xaa\xdc\xbf6E\xd5\xf9`\x01%\x93w\xb5(%\x06.Q)\x01V\xf3\xde\xabZ\xf4>\xb2\x00\xed$\x1f{]\x0b;\x18\xa6>\xa1R\xe1\x8bB\xc6\xec\xd8\xbbR?\xfd\x17\x0c\xfc\xd5\x07\x9b\x95\xe4\xa4\x80C\xabkA*\xe3f\x19?\xa6\xb7\xd9\x85\xd9\xdb%=W\xee\xceW\xb3\xbf3\x96\xba\x05\xbaY\xa3w\x01\x00T\xbeO\xe3\xc0\x01\xcd\xa0'\xbb\x168\xa9\x8b\xf5s\xbb\xcb\xe3b\x0c\xbc\\\xdf\xf6\x81d\x8a\x94\xf5N\x1f\xdb_\xc4\xfb6\xe7W\x1e\xe1|\xc5Yf\xd2\xe6\"S\x9b\xf8P\x96\xa2\x98\x14\xabZ,\xa7\xffP\x14\xbdQ\xe0\x07\xfe'\xa1S\xd4-\x8c7\x11H\xf0\xbc\x8d\x04\x1f\xc7?>\xc1\x9b)\xf3\\\x95\xc1\xad6i1\xb5\xf8>\xa0c\xe2\xa3h>\xe7SUN\xcf\xd3\x9e\xc9\xf5\x03C\xce\x87\x1b\xecV\x87\xbc\xea\xb5j\x8e\xc0\xe7\xfa\x7f\xde\xcc\xab\x00K.\xfdN}\xb6\x03\xb3ws\xa38l-\xf1R:E\xf2&f\xa2yW\n\xd8C\x8alU\xe6\xda\xa6\xa8\xa6\\6E\xa5\xe8p\x9dz\xa5\xa3\x0c\x94\x17\x90\xb2\x9f\x9e\x8b\xdf\x01\x00\x00\xff\xffPK\x07\x08\xdd\xd6\x17\x14\x14\x02\x00\x00\xef\x04\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17\x00\x00\x00templates/search.liquidlR\xcb\x8e\xa40\x10\xbb\xf3\x15\x16\x12\x9a[3s\xe8\x0b\x02~\x05\xa5\xa1\x80h\xf3\xda\xa4\xb2\xa3\x11\xf0\xef+^Mk\xd47\x88]\x8e]\xce\x94\xc1\x89A\x1a\xc1\x84@\xc2\xb7\xe3\xcdS\x88\x8a\x03\x1e?\xf8\xfaD\xb6$@\xd9[\xaf!Z\x96\xd6Ti\xbe\x13Sh\xe2\xd1vU:\x10\xa7\xf0VQ\x95\x1eP\x9d\x00@)\x8d\x8b\x0c\xfeq\x17\x02#4U\xe9\xdf\x14\xff\x84\x8aT\xa5\xd3t^\xcc\xe4u\xc0\x0c\n\xadp\x84e9e\x1e\x91\xd9\x9aS'>\xb4\xe4\xb4\xde\x87\xca|\x07Wf\x99\xaf6\xeb$\x01\xa6\x0c\xb2?u\x1d\xf9\x15\xa0n\x0f\xb3\xa1\xbd\xf5\x90L\x1a\xd2\xfc\xce}\x90N\x91\x95u\xebIp\xf4\xd45R\x8b\x81.\nP\n\x8c\x9e\xfa-\xc7F\x8d^a\xc6\xb7\xe4Q\x9a\x02\xadU\x8a\xb6\xbd\xady\xc0\x92\x15]\xdc\xed\xf7M\xe2\xe3\xfe\xe9\xdd\xe5\xb7\xe0[\xcc\x90zh\xa2W\x05>4u2\xea\x8f\xe3\x8c\xc5P\xbc\x1d\x13\x8a\xb1\xbc\xf8\xceE}\xe5$\xd3\xc9\xfe\x8aU\x8e\xf7\xfa\xb7G%\xcd\x9f\x86mq\xa5\\\x962\x1f\xef\xa7J\xe9\x9e#\xad5L\x861#\xb0\x97\xae\x19Y\xaf;a\x1fM+\x98\xbe\xad\xefB\x81\xfb\xe7\xa6\xe0\xea\xb3\x13R\xe1e\xb5\xc6\xe2h$\xb9L\xae\xb5m\x8cW\xcf\xcf\xbe\xcf\x97|sb\xa0\x80\x1a_\xc8\x96i\xba^\xf8\x8c\x8ez\x11\x157\xc7\xd1\xde\xcb\xab\xd8\xfe\xfd\x9c\xc8\x96\xe4\x7f\x00\x00\x00\xff\xffPK\x07\x08@\x01a\xffx\x01\x00\x00#\x03\x00\x00PK\x01\x02\x14\x00\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\xd8Y\x83\x98\x1e\x00\x00\x00\x18\x00\x00\x00\x1b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00assets/application.css.scssPK\x01\x02\x14\x00\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x11\xad\xdd#.\x00\x00\x00(\x00\x00\x00\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00g\x00\x00\x00assets/application.jsPK\x01\x02\x14\x00\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00s\x98U8<\x00\x00\x00B\x00\x00\x00\x19\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd8\x00\x00\x00config/settings_data.jsonPK\x01\x02\x14\x00\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x8e\x0b\x84\xc8\x97\x00\x00\x00\x1c\x01\x00\x00\x1b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00[\x01\x00\x00config/settings_schema.jsonPK\x01\x02\x14\x00\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00b#~rO\x02\x00\x00{\x05\x00\x00\x13\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00;\x02\x00\x00layout/theme.liquidPK\x01\x02\x14\x00\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\xe5\xb4\xaacr\x00\x00\x00\x8b\x00\x00\x00\x17\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xcb\x04\x00\x00locales/en.default.jsonPK\x01\x02\x14\x00\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\xdc\xdb\xd3\x0fB\x00\x00\x00S\x00\x00\x00\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x82\x05\x00\x00templates/404.liquidPK\x01\x02\x14\x00\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\xeed\xcdfN\x02\x00\x00Y\x06\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x06\x00\x00templates/article.liquidPK\x01\x02\x14\x00\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\xe3fQG\x0b\x01\x00\x00\x1a\x02\x00\x00\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x9a\x08\x00\x00templates/blog.liquidPK\x01\x02\x14\x00\x14\x00\x08\x00\x08\x00\x00\x00\x00\x000\xb7G0C\x02\x00\x00\n\x06\x00\x00\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe8	\x00\x00templates/cart.liquidPK\x01\x02\x14\x00\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\xe1\x0c\x17n3\x01\x00\x00\x9f\x02\x00\x00\x1b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00n\x0c\x00\x00templates/collection.liquidPK\x01\x02\x14\x00\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00L\xb9{)4\x01\x00\x00\x98\x02\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xea\x0d\x00\x00templates/collection.list.liquidPK\x01\x02\x14\x00\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x921\xff\xfa3\x00\x00\x00-\x00\x00\x00\"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00l\x0f\x00\x00templates/customers/account.liquidPK\x01\x02\x14\x00\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\xeb\xdf\xdd|<\x00\x00\x006\x00\x00\x00+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xef\x0f\x00\x00templates/customers/activate_account.liquidPK\x01\x02\x14\x00\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x1by!\xbf5\x00\x00\x00/\x00\x00\x00$\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x84\x10\x00\x00templates/customers/addresses.liquidPK\x01\x02\x14\x00\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\xe03\xbf?1\x00\x00\x00+\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b\x11\x00\x00templates/customers/login.liquidPK\x01\x02\x14\x00\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\xd6\xf0}\x961\x00\x00\x00+\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8a\x11\x00\x00templates/customers/order.liquidPK\x01\x02\x14\x00\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x99l8\x0d4\x00\x00\x00.\x00\x00\x00#\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00	\x12\x00\x00templates/customers/register.liquidPK\x01\x02\x14\x00\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00	\xdd\xe1\x8a:\x00\x00\x004\x00\x00\x00)\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8e\x12\x00\x00templates/customers/reset_password.liquidPK\x01\x02\x14\x00\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\xf0\x94z\xf6\xd6\x01\x00\x00.\x03\x00\x00\x1a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f\x13\x00\x00templates/gift_card.liquidPK\x01\x02\x14\x00\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\xe5\xc8?\xa0\xec\x00\x00\x00\xcb\x01\x00\x00\x16\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00=\x15\x00\x00templates/index.liquidPK\x01\x02\x14\x00\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\n	\xee0b\x01\x00\x00B\x03\x00\x00!\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00m\x16\x00\x00templates/list-collections.liquidPK\x01\x02\x14\x00\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\xc1t\x0b,%\x01\x00\x00\xa0\x02\x00\x00\x1d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1e\x18\x00\x00templates/page.contact.liquidPK\x01\x02\x14\x00\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\xc9\x06\xe5\x902\x00\x00\x008\x00\x00\x00\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8e\x19\x00\x00templates/page.liquidPK\x01\x02\x14\x00\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\xdd\xd6\x17\x14\x14\x02\x00\x00\xef\x04\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x1a\x00\x00templates/product.liquidPK\x01\x02\x14\x00\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00@\x01a\xffx\x01\x00\x00#\x03\x00\x00\x17\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00]\x1c\x00\x00templates/search.liquidPK\x05\x06\x00\x00\x00\x00\x1a\x00\x1a\x00z\x07\x00\x00\x1a\x1e\x00\x00\x00\x00")
+}
\ No newline at end of file
diff --git a/cmd/theme.go b/cmd/theme.go
index b3e856d..aa69f0a 100644
--- a/cmd/theme.go
+++ b/cmd/theme.go
@@ -96,19 +96,12 @@ func init() {
 	openCmd.Flags().BoolVarP(&flags.AllEnvs, "allenvs", "a", false, "run command with all environments")
 	downloadCmd.Flags().BoolVarP(&flags.AllEnvs, "allenvs", "a", false, "run command with all environments")
 	deployCmd.Flags().BoolVarP(&flags.AllEnvs, "allenvs", "a", false, "run command with all environments")
-	newCmd.Flags().StringVar(&flags.Version, "version", "latest", "version of Shopify Timber to use")
-	bootstrapCmd.Flags().StringVar(&flags.Version, "version", "latest", "version of Shopify Timber to use")
 	updateCmd.Flags().StringVar(&flags.Version, "version", "latest", "version of themekit to install")
-	newCmd.Flags().StringVar(&flags.Prefix, "prefix", "", "prefix to the Timber theme being created")
-	newCmd.Flags().StringVar(&flags.URL, "url", "", "a url to pull a project theme zip file from.")
-	newCmd.Flags().StringVar(&flags.Name, "name", "", "a name to define your theme on your shopify admin")
-	bootstrapCmd.Flags().StringVar(&flags.Prefix, "prefix", "", "prefix to the Timber theme being created")
-	bootstrapCmd.Flags().StringVar(&flags.URL, "url", "", "a url to pull a project theme zip file from.")
-	bootstrapCmd.Flags().StringVar(&flags.Name, "name", "", "a name to define your theme on your shopify admin")
+	newCmd.Flags().StringVarP(&flags.Name, "name", "n", "", "a name to define your theme on your shopify admin")
 	openCmd.Flags().BoolVarP(&flags.Edit, "edit", "E", false, "open the web editor for the theme.")
 	openCmd.Flags().StringVarP(&flags.With, "browser", "b", "", "name of the browser to open the url. the name should match the name of browser on your system.")
 	getCmd.Flags().BoolVarP(&flags.List, "list", "l", false, "list available themes.")
 	deployCmd.Flags().BoolVarP(&flags.NoDelete, "nodelete", "n", false, "do no delete file on shopify diring deploy.")
 
-	ThemeCmd.AddCommand(publishCmd, openCmd, versionCmd, bootstrapCmd, newCmd, configureCmd, downloadCmd, removeCmd, updateCmd, uploadCmd, replaceCmd, watchCmd, getCmd, deployCmd)
+	ThemeCmd.AddCommand(publishCmd, openCmd, versionCmd, newCmd, configureCmd, downloadCmd, removeCmd, updateCmd, uploadCmd, replaceCmd, watchCmd, getCmd, deployCmd)
 }
diff --git a/src/cmdutil/_mocks/ShopifyClient.go b/src/cmdutil/_mocks/ShopifyClient.go
index eccecc7..a78b2d7 100644
--- a/src/cmdutil/_mocks/ShopifyClient.go
+++ b/src/cmdutil/_mocks/ShopifyClient.go
@@ -32,20 +32,20 @@ func (_m *ShopifyClient) Themes() ([]shopify.Theme, error) {
 	return r0, r1
 }
 
-// CreateNewTheme provides a mock function with given fields: _a0, _a1
-func (_m *ShopifyClient) CreateNewTheme(_a0 string, _a1 string) (shopify.Theme, error) {
-	ret := _m.Called(_a0, _a1)
+// CreateNewTheme provides a mock function with given fields: _a0
+func (_m *ShopifyClient) CreateNewTheme(_a0 string) (shopify.Theme, error) {
+	ret := _m.Called(_a0)
 
 	var r0 shopify.Theme
-	if rf, ok := ret.Get(0).(func(string, string) shopify.Theme); ok {
-		r0 = rf(_a0, _a1)
+	if rf, ok := ret.Get(0).(func(string) shopify.Theme); ok {
+		r0 = rf(_a0)
 	} else {
 		r0 = ret.Get(0).(shopify.Theme)
 	}
 
 	var r1 error
-	if rf, ok := ret.Get(1).(func(string, string) error); ok {
-		r1 = rf(_a0, _a1)
+	if rf, ok := ret.Get(1).(func(string) error); ok {
+		r1 = rf(_a0)
 	} else {
 		r1 = ret.Error(1)
 	}
diff --git a/src/cmdutil/interfaces.go b/src/cmdutil/interfaces.go
index bff2342..1878025 100644
--- a/src/cmdutil/interfaces.go
+++ b/src/cmdutil/interfaces.go
@@ -7,7 +7,7 @@ import (
 
 type shopifyClient interface {
 	GetShop() (shopify.Shop, error)
-	CreateNewTheme(string, string) (shopify.Theme, error)
+	CreateNewTheme(string) (shopify.Theme, error)
 	GetInfo() (shopify.Theme, error)
 	PublishTheme() error
 	Themes() ([]shopify.Theme, error)
diff --git a/src/shopify/theme_client.go b/src/shopify/theme_client.go
index dbf2296..8a7e486 100644
--- a/src/shopify/theme_client.go
+++ b/src/shopify/theme_client.go
@@ -44,7 +44,6 @@ var (
 type Theme struct {
 	ID          int64  `json:"id,omitempty"`
 	Name        string `json:"name,omitempty"`
-	Source      string `json:"src,omitempty"`
 	Role        string `json:"role,omitempty"`
 	Previewable bool   `json:"previewable,omitempty"`
 	Processing  bool   `json:"processing,omitempty"`
@@ -157,12 +156,8 @@ func (c Client) Themes() ([]Theme, error) {
 
 // CreateNewTheme will create a unpublished new theme on your shopify store and then
 // set the theme id on this theme client to the one recently created.
-func (c *Client) CreateNewTheme(name, zipLocation string) (theme Theme, err error) {
-	if zipLocation == "" {
-		return Theme{}, ErrZipPathRequired
-	}
-
-	resp, err := c.http.Post("/admin/themes.json", map[string]interface{}{"theme": Theme{Name: name, Source: zipLocation}})
+func (c *Client) CreateNewTheme(name string) (theme Theme, err error) {
+	resp, err := c.http.Post("/admin/themes.json", map[string]interface{}{"theme": Theme{Name: name}})
 	if err != nil {
 		return Theme{}, err
 	}
diff --git a/src/static/bundle.go b/src/static/bundle.go
new file mode 100644
index 0000000..d8dcd3c
--- /dev/null
+++ b/src/static/bundle.go
@@ -0,0 +1,98 @@
+// Package static allows for the bundling of static assets into a binary. This
+// allows themekit to bundle files from a theme for generating a new theme.
+package static
+
+import (
+	"archive/zip"
+	"bytes"
+	"fmt"
+	"io/ioutil"
+	"os"
+	"path"
+	"path/filepath"
+	"text/template"
+)
+
+const tmpl = `package {{.PackageName}}
+
+import "github.com/Shopify/themekit/src/static"
+
+func init() {
+	static.Register("{{.Data}}")
+}`
+
+// Bundle takes a directory path and will compress all the data into a single
+// go file with zip data at the dst path.
+func Bundle(src, dst string) error {
+	buffer, err := compressData(src)
+	if err != nil {
+		return err
+	}
+	return writeOutTemplate(dst, buffer)
+}
+
+func compressData(src string) (*bytes.Buffer, error) {
+	buffer := new(bytes.Buffer)
+	zipWriter := zip.NewWriter(buffer)
+	if err := filepath.Walk(src, func(path string, fi os.FileInfo, err error) error {
+		if err != nil || fi.IsDir() {
+			return err
+		}
+		b, err := ioutil.ReadFile(path)
+		if err != nil {
+			return err
+		}
+		relPath, err := filepath.Rel(src, path)
+		if err != nil {
+			return err
+		}
+		f, err := zipWriter.Create(relPath)
+		if err != nil {
+			return err
+		}
+		_, err = f.Write(b)
+		return err
+	}); err != nil {
+		return nil, err
+	}
+	err := zipWriter.Close()
+	return sanitizeData(buffer), err
+}
+
+func sanitizeData(zipData *bytes.Buffer) *bytes.Buffer {
+	dest := new(bytes.Buffer)
+	for _, b := range zipData.Bytes() {
+		switch {
+		case b == '\n':
+			dest.WriteString(`\n`)
+		case b == '\\':
+			dest.WriteString(`\\`)
+		case b == '"':
+			dest.WriteString(`\"`)
+		case b >= 32 && b <= 126 || b == '\t':
+			dest.WriteByte(b)
+		default:
+			fmt.Fprintf(dest, "\\x%02x", b)
+		}
+	}
+	return dest
+}
+
+func writeOutTemplate(dst string, data *bytes.Buffer) error {
+	file, err := os.Create(dst)
+	if err != nil {
+		return err
+	}
+	defer file.Close()
+
+	bundleTemplate, err := template.New("bundle").Parse(tmpl)
+	if err != nil {
+		return err
+	}
+
+	pkg := path.Base(path.Dir(dst))
+	return bundleTemplate.Execute(file, struct {
+		PackageName string
+		Data        *bytes.Buffer
+	}{PackageName: pkg, Data: data})
+}
diff --git a/src/static/cmd/bundle.go b/src/static/cmd/bundle.go
new file mode 100644
index 0000000..f92acee
--- /dev/null
+++ b/src/static/cmd/bundle.go
@@ -0,0 +1,9 @@
+package main
+
+import "github.com/Shopify/themekit/src/static"
+
+func main() {
+	if err := static.Bundle("theme-template", "cmd/static/generated-assets.go"); err != nil {
+		panic(err)
+	}
+}
diff --git a/src/static/unbundle.go b/src/static/unbundle.go
new file mode 100644
index 0000000..2a926ec
--- /dev/null
+++ b/src/static/unbundle.go
@@ -0,0 +1,92 @@
+package static
+
+import (
+	"archive/zip"
+	"io"
+	"os"
+	"path/filepath"
+	"strings"
+
+	"github.com/Shopify/themekit/src/cmdutil"
+	"github.com/Shopify/themekit/src/colors"
+)
+
+var zipData string
+
+// Register will set the zip data that can be decompressed
+func Register(data string) {
+	zipData = data
+}
+
+// Unbundle will saftely put all files in place without overwriting files that
+// already exist
+func Unbundle(ctx *cmdutil.Ctx) error {
+	files, err := getZipContents(zipData)
+	if err != nil {
+		return err
+	}
+	return createDirs(ctx, files)
+}
+
+func getZipContents(data string) (map[string]map[string]*zip.File, error) {
+	files := map[string]map[string]*zip.File{}
+	zipReader, err := zip.NewReader(strings.NewReader(data), int64(len(data)))
+	if err != nil {
+		return files, err
+	}
+	for _, zipFile := range zipReader.File {
+		dir := filepath.Dir(zipFile.Name)
+		if _, ok := files[dir]; !ok {
+			files[dir] = map[string]*zip.File{}
+		}
+		files[dir][zipFile.Name] = zipFile
+	}
+	return files, nil
+}
+
+func createDirs(ctx *cmdutil.Ctx, dirFiles map[string]map[string]*zip.File) error {
+	for dir, files := range dirFiles {
+		dir = filepath.Join(ctx.Flags.Directory, dir)
+		if _, err := os.Stat(dir); os.IsNotExist(err) {
+			if err := os.MkdirAll(dir, 0755); err != nil {
+				return err
+			}
+			ctx.Log.Printf("%s %s.\n", colors.Green("Created"), dir)
+		} else {
+			ctx.Log.Printf("%s %s.\n", colors.Blue("Exists"), dir)
+		}
+		for path, file := range files {
+			path = filepath.Join(ctx.Flags.Directory, path)
+			if err := writeFile(ctx, path, file); err != nil {
+				return err
+			}
+		}
+	}
+	return nil
+}
+
+func writeFile(ctx *cmdutil.Ctx, path string, zfile *zip.File) error {
+	if _, err := os.Stat(path); err == nil {
+		ctx.Log.Printf("\t%s %s.\n", colors.Blue("Exists"), path)
+		return nil
+	}
+
+	file, err := os.Create(path)
+	if err != nil {
+		return err
+	}
+	defer file.Close()
+	defer file.Sync()
+
+	contents, err := zfile.Open()
+	if err != nil {
+		return err
+	}
+	defer contents.Close()
+
+	_, err = io.Copy(file, contents)
+	if err == nil {
+		ctx.Log.Printf("\t%s %s.\n", colors.Green("Created"), file.Name())
+	}
+	return nil
+}
diff --git a/src/timber/release.go b/src/timber/release.go
deleted file mode 100644
index caf2185..0000000
--- a/src/timber/release.go
+++ /dev/null
@@ -1,84 +0,0 @@
-package timber
-
-import (
-	"bytes"
-	"fmt"
-	"net/http"
-	"text/template"
-
-	"github.com/Shopify/themekit/src/atom"
-)
-
-const (
-	timberFeedPath = "https://github.com/Shopify/Timber/releases.atom"
-)
-
-var (
-	invalidVersionTmplt = template.Must(template.New("invalidVersionError").Parse(`Invalid Timber Version: {{ .Requested }}
-  Available Versions Are:
-  - master
-  - latest
-  {{- range .Versions }}
-  - {{ . }}
-  {{- end }}`))
-)
-
-// GetVersionPath will return the download path for a requested version
-func GetVersionPath(version string) (string, error) {
-	return getVersionPath(version, timberFeedPath)
-}
-
-func getVersionPath(version, feedPath string) (string, error) {
-	if version == "master" {
-		return "https://github.com/Shopify/Timber/archive/master.zip", nil
-	}
-
-	feed, err := downloadThemeReleaseAtomFeed(feedPath)
-	if err != nil {
-		return "", err
-	}
-
-	entry, err := findThemeReleaseWith(feed, version)
-	if err != nil {
-		return "", err
-	}
-
-	return "https://github.com/Shopify/Timber/archive/" + entry.Title + ".zip", nil
-}
-
-func downloadThemeReleaseAtomFeed(feedPath string) (atom.Feed, error) {
-	resp, err := http.Get(feedPath)
-	if err != nil {
-		return atom.Feed{}, err
-	}
-	defer resp.Body.Close()
-
-	feed, err := atom.LoadFeed(resp.Body)
-	if err != nil {
-		return atom.Feed{}, err
-	}
-
-	return feed, resp.Body.Close()
-}
-
-func findThemeReleaseWith(feed atom.Feed, version string) (atom.Entry, error) {
-	if version == "latest" {
-		return feed.LatestEntry(), nil
-	}
-
-	entries := []string{}
-	for _, entry := range feed.Entries {
-		if entry.Title == version {
-			return entry, nil
-		}
-		entries = append(entries, entry.Title)
-	}
-
-	var tpl bytes.Buffer
-	invalidVersionTmplt.Execute(&tpl, struct {
-		Requested string
-		Versions  []string
-	}{version, entries})
-
-	return atom.Entry{Title: "Invalid Feed"}, fmt.Errorf(tpl.String())
-}
diff --git a/theme-template/assets/application.css.scss b/theme-template/assets/application.css.scss
new file mode 100644
index 0000000..911f040
--- /dev/null
+++ b/theme-template/assets/application.css.scss
@@ -0,0 +1,1 @@
+// put your styles here
diff --git a/theme-template/assets/application.js b/theme-template/assets/application.js
new file mode 100644
index 0000000..605a34d
--- /dev/null
+++ b/theme-template/assets/application.js
@@ -0,0 +1,1 @@
+// Put your applicaiton javascript here
diff --git a/theme-template/config/settings_data.json b/theme-template/config/settings_data.json
new file mode 100644
index 0000000..7d91411
--- /dev/null
+++ b/theme-template/config/settings_data.json
@@ -0,0 +1,6 @@
+{
+  "current": "Default",
+  "presets": {
+    "Default": { }
+  }
+}
diff --git a/theme-template/config/settings_schema.json b/theme-template/config/settings_schema.json
new file mode 100644
index 0000000..2222269
--- /dev/null
+++ b/theme-template/config/settings_schema.json
@@ -0,0 +1,10 @@
+[
+  {
+    "name": "theme_info",
+    "theme_name": "Themekit template theme",
+    "theme_version": "1.0.0",
+    "theme_author": "Shopify",
+    "theme_documentation_url": "https://github.com/Shopify/themekit",
+    "theme_support_url": "https://github.com/Shopify/themekit/issues"
+  }
+]
diff --git a/theme-template/layout/theme.liquid b/theme-template/layout/theme.liquid
new file mode 100644
index 0000000..8eed1ef
--- /dev/null
+++ b/theme-template/layout/theme.liquid
@@ -0,0 +1,43 @@
+<!doctype html>
+<head>
+  <title>{{ page_title }}</title>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+  <meta name="description" content="{{ page_description | escape }}">
+  <link rel="canonical" href="{{ canonical_url }}">
+  <meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
+  {{ content_for_header }} <!-- Header hook for plugins -->
+  {{ 'application.scss.css' | asset_url | stylesheet_tag }}
+  {{ 'application.js' | asset_url | script_tag }}
+</head>
+<body>
+
+  {% for link in linklists.main-menu.links %}
+    {% assign child_list_handle = link.title | handleize %}
+    {% if linklists[child_list_handle].links != blank %}
+      <a href="{{ link.url }}">{{ link.title }}</a>
+      [{% for childlink in linklists[child_list_handle].links %}
+        <a href="{{ childlink.url }}">{{ childlink.title | escape }}</a>
+      {% endfor %}]
+    {% else %}
+      <a href="{{ link.url }}">{{ link.title }}</a>
+    {% endif %}
+  {% endfor %}
+
+  <a href="/cart">cart</a>
+
+  {% if shop.customer_accounts_enabled %}
+    {% if customer %}
+      <a href="/account">account</a>
+      {{ 'log out'  | customer_logout_link }}
+    {% else %}
+      {{ 'log in ' | customer_login_link }}
+      {{ 'register' | customer_register_link }}
+    {% endif %}
+  {% endif %}
+
+  <main role="main">
+    {{ content_for_layout }}
+  </main>
+</body>
+</html>
diff --git a/theme-template/locales/en.default.json b/theme-template/locales/en.default.json
new file mode 100644
index 0000000..eec5d2a
--- /dev/null
+++ b/theme-template/locales/en.default.json
@@ -0,0 +1,8 @@
+{
+  "general": {
+    "404": {
+      "title": "Not found",
+      "subtext_html": "The page you were looking for does not exist"
+    }
+  }
+}
diff --git a/theme-template/templates/404.liquid b/theme-template/templates/404.liquid
new file mode 100644
index 0000000..1cb23aa
--- /dev/null
+++ b/theme-template/templates/404.liquid
@@ -0,0 +1,2 @@
+<h1>{{ 'general.404.title' | t }}</h1>
+<p>{{ 'general.404.subtext_html' | t }}</p>
diff --git a/theme-template/templates/article.liquid b/theme-template/templates/article.liquid
new file mode 100644
index 0000000..9d2475b
--- /dev/null
+++ b/theme-template/templates/article.liquid
@@ -0,0 +1,41 @@
+{% assign number_of_comments = article.comments_count %}
+{% if comment and comment.created_at %}
+  {% assign number_of_comments = article.comments_count %}
+{% endif %}
+
+<h1>{{ article.title }}</h1>
+{% capture author %}<strong>{{ article.author }}</strong>{% endcapture %}
+{% capture date %}<time datetime="{{ article.published_at | date: '%Y-%m-%d' }}">{{ article.published_at | date: format: 'month_day_year' }}</time>{% endcapture %}
+{{ article.author }} @ {{ article.created_at }}
+
+<div>{{ article.content }}</div>
+{% if blog.comments_enabled? %}
+  <h2>{{ number_of_comments }} comments</h2>
+  {% paginate article.comments by 5 %}
+    {% for comment in article.comments %}
+      <div>
+        <div>{{ comment.content }}</div>
+        {{ comment.author }} @ {{ comment.created_at }}
+      </div>
+    {% endfor %}
+    {% if paginate.pages > 1 %}
+      {{ paginate | default_pagination }}
+    {% endif %}
+  {% endpaginate %}
+
+  <div>
+    {% form 'new_comment', article %}
+      {{ form.errors | default_errors }}
+      <label for="CommentAuthor">name</label>
+      <input type="text" name="comment[author]" id="CommentAuthor" placeholder="name" value="{{ form.author }}" autocapitalize="words">
+
+      <label for="CommentEmail">email</label>
+      <input type="email" name="comment[email]" id="CommentEmail" placeholder="email" value="{{ form.email }}" autocorrect="off" autocapitalize="off">
+
+      <label for="CommentBody">message</label>
+      <textarea name="comment[body]" id="CommentBody" placeholder="message">{{ form.body }}</textarea>
+
+      <input type="submit" value="post">
+    {% endform %}
+  </div>
+{% endif %}
diff --git a/theme-template/templates/blog.liquid b/theme-template/templates/blog.liquid
new file mode 100644
index 0000000..54c3a6b
--- /dev/null
+++ b/theme-template/templates/blog.liquid
@@ -0,0 +1,22 @@
+{% paginate blog.articles by 5 %}
+
+<h1>{{ blog.title }}</h1>
+{% for article in blog.articles %}
+  <div>
+    <h2><a href="{{ article.url }}">{{ article.title }}</a></h2>
+    {{ article.author }} @ {{ article.created_at }}
+    <div>
+      {% if article.excerpt.size > 0 %}
+        {{ article.excerpt }}
+      {% else %}
+        <p>{{ article.content | strip_html | truncatewords: 100 }}</p>
+      {% endif %}
+    </div>
+  </div>
+{% endfor %}
+
+{% if paginate.pages > 1 %}
+  {{ paginate | default_pagination }}
+{% endif %}
+
+{% endpaginate %}
diff --git a/theme-template/templates/cart.liquid b/theme-template/templates/cart.liquid
new file mode 100644
index 0000000..a174e00
--- /dev/null
+++ b/theme-template/templates/cart.liquid
@@ -0,0 +1,46 @@
+{% if cart.item_count > 0 %}
+  <h1>cart</h1>
+  <form action="/cart" method="post" novalidate>
+    <table>
+      <thead>
+        <th colspan="2">Prod</th>
+        <th>Price</th>
+        <th>Qty</th>
+        <th>total</th>
+      </thead>
+      <tbody>
+        {% for item in cart.items %}
+          <tr>
+            <td>
+              <a href="{{ item.url | within: collections.all }}">
+                <img src="{{ item | img_url: 'medium' }}" alt="{{ item.title | escape }}">
+              </a>
+            </td>
+            <td>
+              <a href="{{ item.url }}">{{ item.product.title }}</a>
+              {{ item.variant.title }}
+              <a href="/cart/change?line={{ forloop.index }}&amp;quantity=0">remove</a>
+            </td>
+            <td>{{ item.price | money }}</td>
+            <td>
+              <input type="number" name="updates[]" id="updates_{{ item.key }}" value="{{ item.quantity }}" min="0">
+            </td>
+            <td>
+              {% if item.original_line_price != item.line_price %}{{ item.original_line_price | money }}{% endif %}
+              {{ item.line_price | money }}
+              {% for discount in item.discounts %}{{ discount.title }}{% endfor %}
+            </td>
+          </tr>
+        {% endfor %}
+      </tbody>
+    </table>
+    <div>
+      <p>sub total : {{ cart.total_price | money }}</p>
+      <button type="submit" name="update">Update</button>
+      <button type="submit" name="checkout">Checkout</button>
+    </div>
+  </form>
+{% else %}
+  <h2>cart</h2>
+  Cart is empty
+{% endif %}
diff --git a/theme-template/templates/collection.liquid b/theme-template/templates/collection.liquid
new file mode 100644
index 0000000..dc91d97
--- /dev/null
+++ b/theme-template/templates/collection.liquid
@@ -0,0 +1,18 @@
+{% paginate collection.products by 2 %}
+  <h1>{{ collection.title }}</h1>
+  {% for product in collection.products %}
+    <div>
+      <a href="{{ product.url | within: collection }}">{{ product.title }}</a>
+      {{ product.price | money }}
+      {% unless product.available %}<br><strong>sold out</strong>{% endunless %}
+      <a href="{{ product.url | within: collection }}">
+        <img src="{{ product.featured_image.src | img_url: 'large' }}" alt="{{ product.featured_image.alt | escape }}">
+      </a>
+    </div>
+  {% else %}
+    <p>no matches</p>
+  {% endfor %}
+  {% if paginate.pages > 1 %}
+    {{ paginate | default_pagination }}
+  {% endif %}
+{% endpaginate %}
diff --git a/theme-template/templates/collection.list.liquid b/theme-template/templates/collection.list.liquid
new file mode 100644
index 0000000..7161b43
--- /dev/null
+++ b/theme-template/templates/collection.list.liquid
@@ -0,0 +1,17 @@
+{% paginate collection.products by 2 %}
+  <h1>{{ collection.title }}</h1>
+  {% for product in collection.products %}
+    <div>
+      <a href="{{ product.url | within: collection }}">{{ product.title }}</a>
+      {{ product.price | money }}
+      {% unless product.available %}<br><strong>sold out</strong>{% endunless %}
+      <a href="{{ product.url | within: collection }}">
+        <img src="{{ product.featured_image.src | img_url: 'large' }}" alt="{{ product.featured_image.alt | escape }}">
+      </a>
+    </div>
+  {% else %}
+    <p>no matches</p>
+  {% endfor %}
+  {% if paginate.pages > 1 %}{{ paginate | default_pagination }}{% endif %}
+{% endpaginate %}
+
diff --git a/theme-template/templates/customers/account.liquid b/theme-template/templates/customers/account.liquid
new file mode 100644
index 0000000..2467d93
--- /dev/null
+++ b/theme-template/templates/customers/account.liquid
@@ -0,0 +1,1 @@
+<!-- /templates/customers/account.liquid -->
diff --git a/theme-template/templates/customers/activate_account.liquid b/theme-template/templates/customers/activate_account.liquid
new file mode 100644
index 0000000..fb6add6
--- /dev/null
+++ b/theme-template/templates/customers/activate_account.liquid
@@ -0,0 +1,1 @@
+<!-- /templates/customers/activate_account.liquid -->
diff --git a/theme-template/templates/customers/addresses.liquid b/theme-template/templates/customers/addresses.liquid
new file mode 100644
index 0000000..8bc8bb1
--- /dev/null
+++ b/theme-template/templates/customers/addresses.liquid
@@ -0,0 +1,1 @@
+<!-- /templates/customers/addresses.liquid -->
diff --git a/theme-template/templates/customers/login.liquid b/theme-template/templates/customers/login.liquid
new file mode 100644
index 0000000..37eda2a
--- /dev/null
+++ b/theme-template/templates/customers/login.liquid
@@ -0,0 +1,1 @@
+<!-- /templates/customers/login.liquid -->
diff --git a/theme-template/templates/customers/order.liquid b/theme-template/templates/customers/order.liquid
new file mode 100644
index 0000000..9060a98
--- /dev/null
+++ b/theme-template/templates/customers/order.liquid
@@ -0,0 +1,1 @@
+<!-- /templates/customers/order.liquid -->
diff --git a/theme-template/templates/customers/register.liquid b/theme-template/templates/customers/register.liquid
new file mode 100644
index 0000000..faddf76
--- /dev/null
+++ b/theme-template/templates/customers/register.liquid
@@ -0,0 +1,1 @@
+<!-- /templates/customers/register.liquid -->
diff --git a/theme-template/templates/customers/reset_password.liquid b/theme-template/templates/customers/reset_password.liquid
new file mode 100644
index 0000000..bb449f4
--- /dev/null
+++ b/theme-template/templates/customers/reset_password.liquid
@@ -0,0 +1,1 @@
+<!-- /templates/customers/reset_password.liquid -->
diff --git a/theme-template/templates/gift_card.liquid b/theme-template/templates/gift_card.liquid
new file mode 100644
index 0000000..9f2e15a
--- /dev/null
+++ b/theme-template/templates/gift_card.liquid
@@ -0,0 +1,27 @@
+{% layout none %}
+<!doctype html>
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+  <meta name="viewport" content="width=device-width,initial-scale=1">
+  <meta name="format-detection" content="telephone=no">
+  {{ 'vendor/qrcode.js' | shopify_asset_url | script_tag }}
+</head>
+<body>
+  <div id="qr-code"></div>
+  <script>
+    new QRCode(document.getElementById("qr-code"), {
+      text: "{{ gift_card.qr_identifier }}",
+      width: 120,
+      height: 120
+    });
+  </script>
+  <footer>
+    {% if gift_card.pass_url %}
+    <a href="{{ gift_card.pass_url }}">
+      <img id="apple-wallet-badge" src="{{ 'gift-card/add-to-apple-wallet.svg' | shopify_asset_url }}" width="120" height="40" alt="Add To Apple Wallet">
+    </a>
+    {% endif %}
+  </footer>
+</body>
+</html>
diff --git a/theme-template/templates/index.liquid b/theme-template/templates/index.liquid
new file mode 100644
index 0000000..9f76488
--- /dev/null
+++ b/theme-template/templates/index.liquid
@@ -0,0 +1,10 @@
+{% for product in collections.frontpage.products limit:4 %}
+  <div>
+    <a href="{{ product.url | within: collection }}">{{ product.title }}</a>
+    {{ product.price | money }}
+    {% unless product.available %}<br><strong>sold out</strong>{% endunless %}
+    <a href="{{ product.url | within: collection }}">
+      <img src="{{ product.featured_image.src | img_url: 'large' }}" alt="{{ product.featured_image.alt | escape }}">
+    </a>
+  </div>
+{% endfor %}
diff --git a/theme-template/templates/list-collections.liquid b/theme-template/templates/list-collections.liquid
new file mode 100644
index 0000000..5e36edd
--- /dev/null
+++ b/theme-template/templates/list-collections.liquid
@@ -0,0 +1,17 @@
+{% for collection in collections %}
+  {% unless collection.handle == 'frontpage' %}
+    {% capture collection_title %}{{ collection.title | escape }}{% endcapture %}
+    <a href="{{ collection.url }}">More {{ collection_title }} &rsaquo;</a>
+    {% for product in collection.products limit:5 %}
+      {% assign grid_item_width = 'large--one-fifth medium--one-half' %}
+      <div>
+        <a href="{{ product.url | within: collection }}">{{ product.title }}</a>
+        {{ product.price | money }}
+        {% unless product.available %}<br><strong>sold out</strong>{% endunless %}
+        <a href="{{ product.url | within: collection }}">
+          <img src="{{ product.featured_image.src | img_url: 'large' }}" alt="{{ product.featured_image.alt | escape }}">
+        </a>
+      </div>
+    {% endfor %}
+  {% endunless %}
+{% endfor %}
diff --git a/theme-template/templates/page.contact.liquid b/theme-template/templates/page.contact.liquid
new file mode 100644
index 0000000..8600d36
--- /dev/null
+++ b/theme-template/templates/page.contact.liquid
@@ -0,0 +1,14 @@
+<h1>{{ page.title }}</h1>
+{% form 'contact' %}
+  {% if form.posted_successfully? %} Thank you for your contact {% endif %}
+  {{ form.errors | default_errors }}
+  <label for="ContactFormName">name</label>
+  <input type="text" id="ContactFormName" name="contact[name]">
+  <label for="ContactFormEmail">email</label>
+  <input type="email" id="ContactFormEmail" name="contact[email]">
+  <label for="ContactFormPhone">phone</label>
+  <input type="tel" id="ContactFormPhone" name="contact[phone]">
+  <label for="ContactFormMessage">message</label>
+  <textarea rows="10" id="ContactFormMessage" name="contact[body]"></textarea>
+  <input type="submit" value="send">
+{% endform %}
diff --git a/theme-template/templates/page.liquid b/theme-template/templates/page.liquid
new file mode 100644
index 0000000..9e05a39
--- /dev/null
+++ b/theme-template/templates/page.liquid
@@ -0,0 +1,2 @@
+<h1>{{ page.title }}</h1>
+<div>{{ page.content }}</div>
diff --git a/theme-template/templates/product.liquid b/theme-template/templates/product.liquid
new file mode 100644
index 0000000..f6997ad
--- /dev/null
+++ b/theme-template/templates/product.liquid
@@ -0,0 +1,29 @@
+{% assign current_variant = product.selected_or_first_available_variant %}
+{% assign featured_image = current_variant.featured_image | default: product.featured_image %}
+<img src="{{ featured_image | img_url: 'large' }}" alt="{{ featured_image.alt | escape }}" id="ProductPhotoImg">
+{% for image in product.images %}
+  <a href="{{ image.src | img_url: 'large' }}">
+    <img src="{{ image.src | img_url: 'compact' }}" alt="{{ image.alt | escape }}">
+  </a>
+{% endfor %}
+<h1>{{ product.title }}</h1>
+<form action="/cart/add" method="post" enctype="multipart/form-data" id="AddToCartForm">
+  <select name="id" id="productSelect">
+    {% for variant in product.variants %}
+      {% if variant.available %}
+        <option value="{{ variant.id }}">
+          {{ variant.title }} - {{ variant.price | money_with_currency }}
+        </option>
+      {% else %}
+        <option disabled="disabled">
+          {{ variant.title }} - sold out
+        </option>
+      {% endif %}
+    {% endfor %}
+  </select>
+  {{ current_variant.price | money }}
+  <label for="Quantity">quantity</label>
+  <input type="number" id="Quantity" name="quantity" value="1" min="1">
+  <button type="submit" name="add" id="AddToCart">Add to cart</button>
+</form>
+<div>{{ product.description }}</div>
diff --git a/theme-template/templates/search.liquid b/theme-template/templates/search.liquid
new file mode 100644
index 0000000..7ef5300
--- /dev/null
+++ b/theme-template/templates/search.liquid
@@ -0,0 +1,22 @@
+{% paginate search.results by 10 %}
+  <form action="/search" method="get" role="search">
+    <input type="search" name="q" value="{{ search.terms | escape }}">
+    <button type="submit">search</button>
+  </form>
+
+  {% if search.performed %}
+    {% for item in search.results %}
+      {% if item.featured_image %}
+        <a href="{{ item.url | within: collection }}" title="{{ item.title | escape }}">
+          {{ item.featured_image.src | img_url: 'medium' | img_tag: item.featured_image.alt }}
+        </a>
+      {% endif %}
+      <h5>{{ item.title | link_to: item.url }}</h5>
+      <p>{{ item.content | strip_html | truncatewords: 50 }}</p>
+    {% else %}
+      no results
+    {% endfor %}
+  {% endif %}
+
+  {% if paginate.pages > 1 %}{{ paginate | default_pagination }}{% endif %}
+{% endpaginate %}


Test patch:
diff --git a/cmd/new_test.go b/cmd/new_test.go
index 7a7dc1d..0506a3b 100644
--- a/cmd/new_test.go
+++ b/cmd/new_test.go
@@ -1,6 +1,7 @@
 package cmd
 
 import (
+	"errors"
 	"fmt"
 	"testing"
 
@@ -12,72 +13,41 @@ import (
 )
 
 func TestNewTheme(t *testing.T) {
-	name, url := "name", "https://download.com/1.2.4.zip"
+	name := "name"
 
 	ctx, client, conf, _, _ := createTestCtx()
-	client.On("CreateNewTheme", name, url).Return(shopify.Theme{}, nil)
-	client.On("GetInfo").Return(shopify.Theme{Previewable: true}, nil)
-	client.On("GetAllAssets").Return([]string{}, nil)
-	conf.On("Set", "development", env.Env{}).Return(nil, nil)
+	ctx.Flags.Name = name
+	client.On("CreateNewTheme", name).Return(shopify.Theme{ID: 42}, nil)
+	conf.On("Set", "development", env.Env{ThemeID: "42"}).Return(nil, nil)
 	conf.On("Save").Return(nil)
-	err := newTheme(ctx, name, url)
+	client.On("GetAllAssets").Return([]string{}, nil)
+	err := newTheme(ctx, func(ctx *cmdutil.Ctx) error { return nil })
 	assert.Error(t, err)
 
 	ctx, client, _, _, _ = createTestCtx()
-	client.On("CreateNewTheme", name, url).Return(shopify.Theme{}, fmt.Errorf("can't create theme"))
-	err = newTheme(ctx, name, url)
+	ctx.Flags.Name = name
+	client.On("CreateNewTheme", name).Return(shopify.Theme{}, fmt.Errorf("can't create theme"))
+	err = newTheme(ctx, func(ctx *cmdutil.Ctx) error { return nil })
 	if assert.NotNil(t, err) {
 		assert.Contains(t, err.Error(), "can't create theme")
 	}
 
 	ctx, client, conf, _, _ = createTestCtx()
-	client.On("CreateNewTheme", name, url).Return(shopify.Theme{}, nil)
-	conf.On("Set", "development", env.Env{}).Return(nil, fmt.Errorf("cant set config"))
-	err = newTheme(ctx, name, url)
+	ctx.Flags.Name = name
+	client.On("CreateNewTheme", name).Return(shopify.Theme{ID: 44}, nil)
+	conf.On("Set", "development", env.Env{ThemeID: "44"}).Return(nil, fmt.Errorf("cant set config"))
+	err = newTheme(ctx, func(ctx *cmdutil.Ctx) error { return nil })
 	if assert.NotNil(t, err) {
 		assert.Contains(t, err.Error(), "cant set config")
 	}
 
 	ctx, client, conf, _, _ = createTestCtx()
-	client.On("CreateNewTheme", name, url).Return(shopify.Theme{}, nil)
-	client.On("GetInfo").Return(shopify.Theme{}, fmt.Errorf("oh no"))
-	client.On("GetAllAssets").Return([]string{}, nil)
-	conf.On("Set", "development", env.Env{}).Return(nil, nil)
+	ctx.Flags.Name = name
+	client.On("CreateNewTheme", name).Return(shopify.Theme{ID: 48}, nil)
+	conf.On("Set", "development", env.Env{ThemeID: "48"}).Return(nil, nil)
 	conf.On("Save").Return(nil)
-	err = newTheme(ctx, name, url)
+	err = newTheme(ctx, func(ctx *cmdutil.Ctx) error { return errors.New("oh no") })
 	if assert.NotNil(t, err) {
 		assert.Contains(t, err.Error(), "oh no")
 	}
 }
-
-func TestGetNewThemeDetails(t *testing.T) {
-	getVerGood := func(string) (string, error) { return "https://download.com", nil }
-	getVerBad := func(string) (string, error) { return "", fmt.Errorf("cant fetch releases") }
-
-	testcases := []struct {
-		in, iu, on, ou, err string
-		handler             func(string) (string, error)
-	}{
-		{on: "preTimber-latest", ou: "https://download.com", handler: getVerGood},
-		{on: "preTimber-latest", ou: "", handler: getVerBad, err: "cant fetch releases"},
-		{iu: "https://download.com/1.2.4.zip", on: "pre1.2.4", ou: "https://download.com/1.2.4.zip", handler: getVerGood},
-		{in: "name", iu: "https://download.com/1.2.4.zip", on: "name", ou: "https://download.com/1.2.4.zip", handler: getVerBad},
-	}
-
-	for _, testcase := range testcases {
-		flags := cmdutil.Flags{
-			Name:    testcase.in,
-			URL:     testcase.iu,
-			Version: "latest",
-			Prefix:  "pre",
-		}
-		name, url, err := getNewThemeDetails(flags, testcase.handler)
-		assert.Equal(t, testcase.on, name)
-		assert.Equal(t, testcase.ou, url)
-		if testcase.err == "" {
-			assert.Nil(t, err)
-		} else if assert.NotNil(t, err) {
-			assert.Contains(t, err.Error(), testcase.err)
-		}
-	}
-}
diff --git a/src/shopify/theme_client_test.go b/src/shopify/theme_client_test.go
index 6ae6bd3..87826d4 100644
--- a/src/shopify/theme_client_test.go
+++ b/src/shopify/theme_client_test.go
@@ -114,22 +114,21 @@ func TestThemeClient_Themes(t *testing.T) {
 
 func TestThemeClient_CreateNewTheme(t *testing.T) {
 	testcases := []struct {
-		in                 []string
+		in                 string
 		theme              Theme
 		resp, resperr, err string
 	}{
-		{in: []string{"", "https://githubz.com/shopify/timberlands"}, resp: `{"errors":{"name":["can't be blank"]}}`, err: "name can't be blank"},
-		{in: []string{"my theme", "https://githubz.com/shopify/timberlands"}, resp: `{"errors": "Not Found"}`, err: "Not Found"},
-		{in: []string{"my theme", ""}, err: "theme zip path is required"},
-		{in: []string{"my theme", "https://githubz.com/shopify/timberlands"}, resperr: "(Client.Timeout exceeded while awaiting headers)", err: "(Client.Timeout exceeded while awaiting headers)"},
-		{in: []string{"my theme", "https://githubz.com/shopify/timberlands"}, resp: `{"theme":{"id": 123456,"name":"timberland","role":"unpublished","previewable":false}}`},
+		{in: "", resp: `{"errors":{"name":["can't be blank"]}}`, err: "name can't be blank"},
+		{in: "my theme", resp: `{"errors": "Not Found"}`, err: "Not Found"},
+		{in: "my theme", resperr: "(Client.Timeout exceeded while awaiting headers)", err: "(Client.Timeout exceeded while awaiting headers)"},
+		{in: "my theme", resp: `{"theme":{"id": 123456,"name":"timberland","role":"unpublished","previewable":false}}`},
 	}
 
 	for _, testcase := range testcases {
 		client, _ := NewClient(&env.Env{})
 		m := new(mocks.HttpAdapter)
 		client.http = m
-		query := map[string]interface{}{"theme": Theme{Name: testcase.in[0], Source: testcase.in[1]}}
+		query := map[string]interface{}{"theme": Theme{Name: testcase.in}}
 
 		if testcase.resp != "" {
 			m.On("Post", "/admin/themes.json", query).Return(jsonResponse(testcase.resp, 200), nil)
@@ -137,7 +136,7 @@ func TestThemeClient_CreateNewTheme(t *testing.T) {
 			m.On("Post", "/admin/themes.json", query).Return(nil, errors.New(testcase.resperr))
 		}
 
-		theme, err := client.CreateNewTheme(testcase.in[0], testcase.in[1])
+		theme, err := client.CreateNewTheme(testcase.in)
 
 		if testcase.err == "" {
 			assert.Nil(t, err)
diff --git a/src/static/_testdata/static/generated-assets.go b/src/static/_testdata/static/generated-assets.go
new file mode 100644
index 0000000..fdab26d
--- /dev/null
+++ b/src/static/_testdata/static/generated-assets.go
@@ -0,0 +1,7 @@
+package static
+
+import "github.com/Shopify/themekit/src/static"
+
+func init() {
+	static.Register("PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15\x00\x00\x00assets/application.js\xd2\xd7W\x08(-Q\xa8\xcc/-RH,(\xc8\xc9LN\xcc,\xc9\xcfS\xc8J,K,N.\xca,(Q\xc8H-J\xe5\x02\x04\x00\x00\xff\xffPK\x07\x08\x11\xad\xdd#.\x00\x00\x00(\x00\x00\x00PK\x01\x02\x14\x00\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x11\xad\xdd#.\x00\x00\x00(\x00\x00\x00\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00assets/application.jsPK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x00C\x00\x00\x00q\x00\x00\x00\x00\x00")
+}
\ No newline at end of file
diff --git a/src/static/_testdata/theme-template/assets/application.js b/src/static/_testdata/theme-template/assets/application.js
new file mode 100644
index 0000000..605a34d
--- /dev/null
+++ b/src/static/_testdata/theme-template/assets/application.js
@@ -0,0 +1,1 @@
+// Put your applicaiton javascript here
diff --git a/src/static/bundle_test.go b/src/static/bundle_test.go
new file mode 100644
index 0000000..5b36920
--- /dev/null
+++ b/src/static/bundle_test.go
@@ -0,0 +1,43 @@
+package static
+
+import (
+	"bytes"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestCompressData(t *testing.T) {
+	buffer, err := compressData("_testdata/theme-template")
+	assert.Nil(t, err)
+	expected := "PK\\x03\\x04\\x14\\x00\\x08\\x00\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x15\\x00\\x00\\x00assets/application.js\\xd2\\xd7W\\x08(-Q\\xa8\\xcc/-RH,(\\xc8\\xc9LN\\xcc,\\xc9\\xcfS\\xc8J,K,N.\\xca,(Q\\xc8H-J\\xe5\\x02\\x04\\x00\\x00\\xff\\xffPK\\x07\\x08\\x11\\xad\\xdd#.\\x00\\x00\\x00(\\x00\\x00\\x00PK\\x01\\x02\\x14\\x00\\x14\\x00\\x08\\x00\\x08\\x00\\x00\\x00\\x00\\x00\\x11\\xad\\xdd#.\\x00\\x00\\x00(\\x00\\x00\\x00\\x15\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00assets/application.jsPK\\x05\\x06\\x00\\x00\\x00\\x00\\x01\\x00\\x01\\x00C\\x00\\x00\\x00q\\x00\\x00\\x00\\x00\\x00"
+	assert.Equal(t, expected, buffer.String())
+
+	_, err = compressData("_testdata/nope")
+	assert.Error(t, err)
+}
+
+func TestWriteOutTemplate(t *testing.T) {
+	path := "_testdata/out/foo.go"
+	os.Mkdir(filepath.Dir(path), 0755)
+	defer os.RemoveAll(filepath.Dir(path))
+	err := writeOutTemplate(path, bytes.NewBuffer([]byte("a test file")))
+	assert.Nil(t, err)
+	f, _ := os.Open(path)
+	defer f.Close()
+	data, _ := ioutil.ReadAll(f)
+	expected := `package out
+
+import "github.com/Shopify/themekit/src/static"
+
+func init() {
+	static.Register("a test file")
+}`
+	assert.Equal(t, expected, string(data[:]))
+
+	err = writeOutTemplate("_testdata/nope/no.go", bytes.NewBuffer([]byte("a test file")))
+	assert.NotNil(t, err)
+}
diff --git a/src/static/unbundle_test.go b/src/static/unbundle_test.go
new file mode 100644
index 0000000..29a3511
--- /dev/null
+++ b/src/static/unbundle_test.go
@@ -0,0 +1,60 @@
+package static
+
+import (
+	"bytes"
+	"fmt"
+	"log"
+	"os"
+	"path/filepath"
+	"testing"
+
+	"github.com/Shopify/themekit/src/cmdutil"
+	"github.com/stretchr/testify/assert"
+)
+
+const testData = "PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15\x00\x00\x00assets/application.js\xd2\xd7W\x08(-Q\xa8\xcc/-RH,(\xc8\xc9LN\xcc,\xc9\xcfS\xc8J,K,N.\xca,(Q\xc8H-J\xe5\x02\x04\x00\x00\xff\xffPK\x07\x08\x11\xad\xdd#.\x00\x00\x00(\x00\x00\x00PK\x01\x02\x14\x00\x14\x00\x08\x00\x08\x00\x00\x00\x00\x00\x11\xad\xdd#.\x00\x00\x00(\x00\x00\x00\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00assets/application.jsPK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x00C\x00\x00\x00q\x00\x00\x00\x00\x00"
+
+func TestGetZipContents(t *testing.T) {
+	files, err := getZipContents(testData)
+	assert.Nil(t, err)
+	assert.Equal(t, 1, len(files))
+	assert.NotNil(t, files["assets"])
+	assert.Equal(t, 1, len(files["assets"]))
+	assert.NotNil(t, files["assets"]["assets/application.js"])
+
+	_, err = getZipContents("not zip")
+	assert.EqualError(t, err, "zip: not a valid zip file")
+}
+
+func TestUnbundle(t *testing.T) {
+	testdirpath := filepath.Join("_testdata", "out")
+	os.Mkdir(filepath.Dir(testdirpath), 0755)
+	defer os.RemoveAll(testdirpath)
+
+	stdOut := bytes.NewBufferString("")
+	ctx := &cmdutil.Ctx{
+		Flags: cmdutil.Flags{Directory: testdirpath},
+		Log:   log.New(stdOut, "", 0),
+	}
+
+	Register(testData)
+	assert.Nil(t, Unbundle(ctx))
+
+	files := map[string][]string{}
+	filepath.Walk(testdirpath, func(path string, info os.FileInfo, err error) error {
+		if err != nil || info.IsDir() {
+			return err
+		}
+		dir := filepath.Dir(path)
+		files[dir] = append(files[dir], path)
+		return nil
+	})
+
+	fmt.Println(files)
+	assert.Equal(t, 1, len(files))
+	assert.Equal(t, 1, len(files[filepath.Join(testdirpath, "assets")]))
+	assert.Equal(t,
+		[]string{filepath.Join(testdirpath, "assets", "application.js")},
+		files[filepath.Join(testdirpath, "assets")],
+	)
+}
diff --git a/src/timber/release_test.go b/src/timber/release_test.go
deleted file mode 100644
index 8703d2a..0000000
--- a/src/timber/release_test.go
+++ /dev/null
@@ -1,94 +0,0 @@
-package timber
-
-import (
-	"fmt"
-	"net/http"
-	"net/http/httptest"
-	"strings"
-	"testing"
-
-	"github.com/stretchr/testify/assert"
-
-	"github.com/Shopify/themekit/src/atom"
-)
-
-const releaseAtom = `<?xml version="1.0" encoding="UTF-8"?>
-<feed xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xml:lang="en-US">
-  <entry> <title>v2.0.2</title> </entry>
-  <entry><title>v2.0.1</title></entry>
-  <entry><title>v2.0.0</title></entry>
-  <entry><title>v1.3.1</title></entry>
-  <entry><title>v1.0.0</title></entry>
-</feed>`
-
-func TestGetVersionPath(t *testing.T) {
-	testcases := []struct {
-		version, path, err string
-	}{
-		{version: "master", path: "https://github.com/Shopify/Timber/archive/master.zip"},
-		{version: "v1.3.1", path: "https://github.com/Shopify/Timber/archive/v1.3.1.zip"},
-		{version: "latest", path: "https://github.com/Shopify/Timber/archive/v2.0.2.zip"},
-		{version: "v1.3.0", err: "Available Versions Are"},
-	}
-
-	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		fmt.Fprintln(w, releaseAtom)
-	}))
-	defer ts.Close()
-
-	for _, testcase := range testcases {
-		path, err := getVersionPath(testcase.version, ts.URL+"/feed")
-		if testcase.err == "" {
-			assert.Nil(t, err)
-			assert.Equal(t, path, testcase.path)
-		} else if assert.NotNil(t, err, testcase.err) {
-			assert.Contains(t, err.Error(), testcase.err)
-		}
-	}
-
-	ts.Close()
-	_, err := getVersionPath("latest", ts.URL+"/feed")
-	assert.NotNil(t, err)
-}
-
-func TestDownloadThemeReleaseAtomFeed(t *testing.T) {
-	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		fmt.Fprintln(w, releaseAtom)
-	}))
-	_, err := downloadThemeReleaseAtomFeed(ts.URL)
-	ts.Close()
-	assert.Nil(t, err)
-	_, err = downloadThemeReleaseAtomFeed(ts.URL)
-	assert.NotNil(t, err)
-
-	ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		fmt.Fprintln(w, "this is not an atom feed")
-	}))
-	defer ts.Close()
-	_, err = downloadThemeReleaseAtomFeed(ts.URL)
-	if assert.NotNil(t, err) {
-		assert.Contains(t, err.Error(), "EOF")
-	}
-}
-
-func TestFindThemeReleaseWith(t *testing.T) {
-	feed, _ := atom.LoadFeed(strings.NewReader(releaseAtom))
-
-	testcases := []struct {
-		version, path, err string
-	}{
-		{version: "v1.3.1", path: "v1.3.1"},
-		{version: "latest", path: "v2.0.2"},
-		{version: "v1.3.0", err: "Available Versions Are"},
-	}
-
-	for _, testcase := range testcases {
-		entry, err := findThemeReleaseWith(feed, testcase.version)
-		if testcase.err == "" {
-			assert.Nil(t, err)
-			assert.Equal(t, entry.Title, testcase.path)
-		} else if assert.NotNil(t, err, testcase.err) {
-			assert.Contains(t, err.Error(), testcase.err)
-		}
-	}
-}