shopify_app_lrb3 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/CHANGELOG +5 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE +19 -0
  6. data/README.md +182 -0
  7. data/RELEASING +16 -0
  8. data/Rakefile +11 -0
  9. data/install.rb +25 -0
  10. data/lib/generators/shopify_app/README +23 -0
  11. data/lib/generators/shopify_app/USAGE +22 -0
  12. data/lib/generators/shopify_app/shopify_app_generator.rb +69 -0
  13. data/lib/generators/shopify_app/templates/app/assets/images/favicon.png +0 -0
  14. data/lib/generators/shopify_app/templates/app/assets/images/grid-18px.png +0 -0
  15. data/lib/generators/shopify_app/templates/app/assets/images/shopify-114.png +0 -0
  16. data/lib/generators/shopify_app/templates/app/assets/images/shopify-57.png +0 -0
  17. data/lib/generators/shopify_app/templates/app/assets/images/shopify-72.png +0 -0
  18. data/lib/generators/shopify_app/templates/app/assets/images/shopify.png +0 -0
  19. data/lib/generators/shopify_app/templates/app/assets/javascripts/application.js +15 -0
  20. data/lib/generators/shopify_app/templates/app/assets/stylesheets/application.css +10 -0
  21. data/lib/generators/shopify_app/templates/app/assets/stylesheets/imports.css.less +5 -0
  22. data/lib/generators/shopify_app/templates/app/assets/stylesheets/shopify_app.css.scss +150 -0
  23. data/lib/generators/shopify_app/templates/app/assets/stylesheets/shopify_app_buttons.css.less +77 -0
  24. data/lib/generators/shopify_app/templates/app/controllers/application_controller.rb +13 -0
  25. data/lib/generators/shopify_app/templates/app/controllers/home_controller.rb +18 -0
  26. data/lib/generators/shopify_app/templates/app/controllers/sessions_controller.rb +52 -0
  27. data/lib/generators/shopify_app/templates/app/helpers/home_helper.rb +9 -0
  28. data/lib/generators/shopify_app/templates/app/helpers/login_helper.rb +3 -0
  29. data/lib/generators/shopify_app/templates/app/helpers/tabs_helper.rb +11 -0
  30. data/lib/generators/shopify_app/templates/app/views/home/design.html.erb +3542 -0
  31. data/lib/generators/shopify_app/templates/app/views/home/index.html.erb +168 -0
  32. data/lib/generators/shopify_app/templates/app/views/home/welcome.html.erb +110 -0
  33. data/lib/generators/shopify_app/templates/app/views/layouts/application.html.erb +79 -0
  34. data/lib/generators/shopify_app/templates/app/views/sessions/new.html.erb +21 -0
  35. data/lib/generators/shopify_app/templates/config/initializers/omniauth.rb +14 -0
  36. data/lib/generators/shopify_app/templates/config/initializers/shopify_session_repository.rb +21 -0
  37. data/lib/generators/shopify_app/templates/public/404.html +40 -0
  38. data/lib/generators/shopify_app/templates/public/422.html +40 -0
  39. data/lib/generators/shopify_app/templates/public/500.html +40 -0
  40. data/lib/generators/shopify_app/templates/public/favicon.png +0 -0
  41. data/lib/generators/shopify_app/templates/public/shopify-114.png +0 -0
  42. data/lib/generators/shopify_app/templates/public/shopify-57.png +0 -0
  43. data/lib/generators/shopify_app/templates/public/shopify-72.png +0 -0
  44. data/lib/shopify_app.rb +20 -0
  45. data/lib/shopify_app/configuration.rb +46 -0
  46. data/lib/shopify_app/in_memory_session_store.rb +25 -0
  47. data/lib/shopify_app/login_protection.rb +39 -0
  48. data/lib/shopify_app/railtie.rb +17 -0
  49. data/lib/shopify_app/shopify_session_repository.rb +22 -0
  50. data/lib/shopify_app/version.rb +3 -0
  51. data/shipit.rubygems.yml +1 -0
  52. data/shopify_app.gemspec +30 -0
  53. data/test/config/development_config_file.yml +7 -0
  54. data/test/config/empty_config_file.yml +1 -0
  55. data/test/config/other_config_file.yml +3 -0
  56. data/test/config/shopify_app.yml +3 -0
  57. data/test/lib/shopify_app/configuration_test.rb +78 -0
  58. data/test/lib/shopify_app/in_memory_session_store_test.rb +35 -0
  59. data/test/lib/shopify_app/shopify_session_repository_test.rb +57 -0
  60. data/test/test_helper.rb +5 -0
  61. metadata +214 -0
@@ -0,0 +1,168 @@
1
+ <header class="jumbotron">
2
+ <div class="inner">
3
+ <div class="container">
4
+ <h1 style="letter-spacing:-3px; margin-bottom:20px;">Where do I start?</h1>
5
+ <p class="lead">An <strong>intro</strong> to using the Shopify App Template<br/>
6
+ including information on the <strong>Shopify API</strong> and <strong>Bootstrap,</strong><br/>
7
+ just to get the ball rolling.</p>
8
+ </div><!-- /container -->
9
+ </div>
10
+ </header>
11
+
12
+ <div class="row">
13
+ <div class="span3">
14
+ <div class="well">
15
+ <h3>Check out the <code>home_controller</code></h3>
16
+ <hr style="margin:2px 0 7px"/>
17
+ <p>The controller in this demo application fetches the newest 5 orders and products and makes them available as instance variables <code>@orders</code> and <code>@products</code></p>
18
+
19
+ <br/>
20
+
21
+ <h3>Take a look at <code>index.html.erb</code></h3>
22
+ <hr style="margin:2px 0 7px"/>
23
+ <p>Index is the Ruby template you are currently viewing. Have a look at the markup and Ruby code to see how the Shopify API is being used. It's located at <code>views/home/index.html.erb</code></p>
24
+ </div>
25
+
26
+ <h3>Additional Docs</h3>
27
+ <p>You can become an expert pretty quickly by reading up on these docs:</p>
28
+
29
+ <ul>
30
+ <li>
31
+ <%= link_to 'API documentation', 'http://www.shopify.com/developers/api/' %>
32
+ <span class="note">Learn what you can do with the Shopify API</span>
33
+ </li><br/>
34
+ <li>
35
+ <%= link_to 'Bootstrap documentation', 'http://twitter.github.com/bootstrap/' %>
36
+ <span class="note">Find out what you can do with Twitter Bootstrap</span>
37
+ </li><br/>
38
+ <li>
39
+ <%= link_to 'Wiki', 'http://wiki.shopify.com/' %>
40
+ <span class="note">Get more information and share your knowledge</span>
41
+ </li><br/>
42
+ <li>
43
+ <%= link_to 'Forum', 'http://forums.shopify.com/community' %>
44
+ <span class="note">Ask questions and see what others already wanted to know</span>
45
+ </li>
46
+ </ul>
47
+
48
+ <hr/>
49
+
50
+ <h3>Once you're ready</h3>
51
+
52
+ <p>We'd love to see what you create using the Shopify API. You can keep up to date on the latest and greatest via the <%= link_to 'Shopify API Twitter Account', 'http://www.twitter.com/shopifyapi' %>. You can also read the latest information on the <%= link_to 'API Publishing Page', 'http://www.shopify.com/developers/publishing/' %>.</p>
53
+
54
+ <br/>
55
+
56
+ <a href="https://twitter.com/shopifyapi" class="twitter-follow-button" data-show-count="false" data-size="large">Follow @shopifyapi</a>
57
+ <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
58
+ </div> <!-- span3 / left-column -->
59
+
60
+
61
+ <div class="span8 offset1">
62
+ <h2>Recent orders</h2>
63
+
64
+ <% if @orders.blank? %>
65
+ <table class="table table-striped">
66
+ <tr>
67
+ <td><em>There are no orders in your store.</em></td>
68
+ </tr>
69
+ </table>
70
+
71
+ <% else %>
72
+
73
+ <table class="table table-striped">
74
+ <thead>
75
+ <tr>
76
+ <th>Order</th>
77
+ <th>Placed by</th>
78
+ <th>Paid</th>
79
+ <th>Fulfillment</th>
80
+ <th>Total</th>
81
+ </tr>
82
+ </thead>
83
+ <% @orders.each do |order| %>
84
+ <tr>
85
+ <td><%= link_to order.name, "https://#{shop_session.url}/admin/orders/#{order.id}", :target => 'blank' %></td>
86
+ <td><%= customer_name(order) %></td>
87
+ <td>
88
+ <span class="label <% if order.financial_status == 'paid' %>label-success<% end %> <% if order.financial_status == 'pending' %>label-warning<% end %> <% if order.financial_status == 'refunded' %>label-important<% end %>"><%= order.financial_status %>
89
+ </span>
90
+ </td>
91
+ <td>
92
+ <% if !order.fulfillment_status %>
93
+ <span class="label">Not Fulfilled</span>
94
+ <% else %>
95
+ <span class="label label-success">Fulfilled</span>
96
+ <% end %>
97
+ </td>
98
+ <td><%= order.total_price %> <%= order.currency %></td>
99
+ </tr>
100
+ <% end %>
101
+ </table>
102
+
103
+ <% end %>
104
+
105
+ <br/>
106
+
107
+ <h2>New Products</h2>
108
+
109
+ <div class="accordion" id="accordion">
110
+
111
+ <% if @products.blank? %>
112
+
113
+ <div class="accordion-group">
114
+ <div class="accordion-heading">
115
+ <em>There are no products in your store.</em>
116
+ </div>
117
+ </div>
118
+
119
+ <% else %>
120
+
121
+ <% @products.each_with_index do |product, index| %>
122
+ <div class="accordion-group">
123
+ <div class="accordion-heading">
124
+
125
+ <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion" href="#<%= product.id %>">
126
+ <%= product.title %> <span class="pull-right muted"><%= product.price_range %> <%= shop_session.shop.currency %></span>
127
+ </a>
128
+ </div>
129
+
130
+ <div id="<%= product.id %>" class="accordion-body collapse <% if index == 1 %>in<% end %>">
131
+ <div class="accordion-inner">
132
+
133
+ <% if !product.images.empty? %>
134
+ <div class="polaroid">
135
+ <%= link_to image_tag(product.images.first.medium), '#modal-'+product.id.to_s, :'data-toggle' => 'modal' %>
136
+ </div>
137
+ <% end %>
138
+
139
+ <p><strong>Type:</strong> <%= product.product_type %></p>
140
+ <p><strong>Vendor:</strong> <%= product.vendor %></p>
141
+ <p><%= raw(product.body_html) %></p><br/>
142
+ <% if product.published_at != nil %>
143
+ <p class="muted">Published at <%= Time.parse(product.published_at).strftime("%H:%M on %m/%d/%Y") %></p>
144
+ <% end %>
145
+ <p><%= link_to raw('View in your Shopify Admin <i class="icon-chevron-right" style="opacity:.25"></i>'), "https://#{shop_session.url}/admin/products/#{product.id}", :target => 'blank', :class => 'btn btn-primary' %></p>
146
+ </div>
147
+
148
+ </div>
149
+ </div>
150
+
151
+ <div class="modal hide fade" id="modal-<%= product.id %>" style="display:none;">
152
+ <div class="modal-header">
153
+ <a class="close" data-dismiss="modal">×</a>
154
+ <h3><%= product.title %></h3>
155
+ </div>
156
+ <div class="modal-body" >
157
+ <% if !product.images.empty? %>
158
+ <%= image_tag product.images.first.large %>
159
+ <% end %>
160
+ </div>
161
+ </div>
162
+ <% end %>
163
+
164
+ <% end %>
165
+
166
+ </div> <!-- accordion -->
167
+ </div> <!-- span8 / right-column -->
168
+ </div>
@@ -0,0 +1,110 @@
1
+ <h1 class="green">Welcome</h1>
2
+
3
+ <p>
4
+ This is an example Shopify application that shows what you can do with the Shopify API.
5
+ </p>
6
+
7
+ <div class="info" style="clear: both">
8
+ This will send the <strong>API-Key</strong> and <strong>Secret</strong> to a shop, and make sure that you have the rights to
9
+ access its private admin data.<br/>
10
+ After authenticating, you will be redirected to the <code>show</code> action of your <code>SessionsController</code>, which stores the session, and then redirects you to your example dashboard.<br/>
11
+ Your <code>HomeController</code> will get your recent <code>Orders</code> and <code>Articles</code> through the
12
+ Shopify <%= link_to 'REST', 'http://www.xfront.com/REST-Web-Services.html', :title => "Get more information about REST web services in general" %> API and list them with all of your <code>Products</code>.
13
+ You can click on a link of one of your objects and will then be taken to the corresponding admin area of your shop.<br/>
14
+
15
+ <p><strong>Note:</strong> There are no examples for <em>creating or editing</em> objects, but you are also able to do that with the Shopify API!</p>
16
+ </div>
17
+
18
+ <h3>1. Make sure you've entered a valid <em>API-Key</em> and <em>Secret</em></h3>
19
+
20
+ <ul style="list-style-type: lower-alpha;">
21
+ <li>
22
+ <p>
23
+ If you haven't registered your application yet, then enter your shop's <strong>URL</strong> or <strong>subdomain</strong> here:<br/>
24
+ </p>
25
+
26
+ <div class="box grey" style="width: 500px;text-align: center">
27
+ <script type="text/javascript" charset="utf-8">
28
+ function getApiUrl() {
29
+ var name = $('shop').value;
30
+ if (name.indexOf('.') == -1) {
31
+ var api_url = name + '.myshopify.com';
32
+ } else {
33
+ var api_url = name.replace(/^https?:\/\//, ''); // Remove the "http://"
34
+ }
35
+ api_url = api_url.replace(/\/$/, ''); // Trim trailing slashes
36
+ $('api-form').action = 'http://' + api_url + '/admin/api_clients/new';
37
+ }
38
+ </script>
39
+
40
+ <% form_tag '', :method => 'get', :id => 'api-form', :onsubmit => "getApiUrl(); return true;", :style => 'margin-left: 16px;' do %>
41
+ <%= text_field_tag 'shop', '', :size => 40 %>
42
+ <%= hidden_field_tag 'api_client[return_url]', @callback_url %>
43
+ <%= submit_tag 'Get API key' %>
44
+ <% end %>
45
+ </div>
46
+
47
+ <p>
48
+ After registering your application with Shopify, you need to edit the <code>config/shopify.yml</code> file,
49
+ and insert your <em>API-Key</em> and <em>Secret</em> there. Then restart this application.
50
+ </p>
51
+ </li>
52
+ <li>
53
+ <p><strong>If you've already supplied those to the generator</strong>, then move on to <%= link_to 'Step #2', '#callback-step' %>.</p>
54
+ </li>
55
+ </ul>
56
+
57
+ <h3 id="callback-step">2. Make sure your <em>callback URL</em> is correct</h3>
58
+
59
+ The URL should be <code><%= @callback_url %></code>,
60
+ with the host portion of the URL pointing to whichever domain is currently hosting this application. <br/>
61
+ The callback URL of your app can be changed in the API screen of your Shopify admin interface.
62
+
63
+ <h3>3. <%= link_to 'Login', '/login' %> to your shop</h3>
64
+
65
+ <div class="border-wrap">
66
+ <div class="info">
67
+ This will send the <strong>API-Key</strong> and <strong>Secret</strong> to a shop, and make sure that you have the rights to
68
+ access its private admin data.<br/>
69
+ After authenticating, you will be redirected to the <code>show</code> action of your <code>SessionsController</code>, which stores the session, and then redirects you to your example dashboard.<br/>
70
+ Your <code>HomeController</code> will get your recent <code>Orders</code> and <code>Articles</code> through the
71
+ Shopify <%= link_to 'REST', 'http://www.xfront.com/REST-Web-Services.html', :title => "Get more information about REST web services in general" %> API and list them with all of your <code>Products</code>.
72
+ You can click on a link of one of your objects and will then be taken to the corresponding admin area of your shop.<br/>
73
+
74
+ <p><strong>Note:</strong> There are no examples for <em>creating or editing</em> objects, but you are also able to do that with the Shopify API!</p>
75
+ </div>
76
+ </div>
77
+
78
+ <h3>4. Check out the source code of the <code>home_controller</code> and its <code>index</code> template</h3>
79
+
80
+ <p class="description">
81
+ You can analyze those files to see how the ShopifyAPI is used and get a glimpse of what's possible.
82
+ </p>
83
+
84
+ <h3>5. Read additional documentation</h3>
85
+
86
+ <p class="description">
87
+ Become an expert.
88
+ </p>
89
+
90
+ <ul>
91
+ <li>
92
+ <%= link_to 'API documentation', 'http://www.shopify.com/developers/api' %>
93
+ <span class="hint">(An overview of what you can do with the Shopify API.)
94
+ </li>
95
+ <li>
96
+ <%= link_to 'Wiki (needs its own API section)', 'http://wiki.shopify.com/' %>
97
+ <span class="hint">(Get more information and share your knowledge.)
98
+ </li>
99
+ <li>
100
+ <%= link_to 'Forum (needs its own API section)', 'http://forums.shopify.com/community' %>
101
+ <span class="hint">(Ask questions and see what others already wanted to know.)
102
+ </li>
103
+ </ul>
104
+
105
+ <h3>6. Publish your application</h3>
106
+
107
+ <p class="description">
108
+ This feature is not implemented yet, but it in the future it will allow you to register your application,
109
+ so that will be shown in a public directory with a description, so that more users will take notice of it.
110
+ </p>
@@ -0,0 +1,79 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <title>Shopify Demo App</title>
5
+ <%= stylesheet_link_tag 'application' %>
6
+ <%= javascript_include_tag 'application' %>
7
+ <%= csrf_meta_tags %>
8
+
9
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
10
+ <link href='http://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'>
11
+
12
+ <!-- icons -->
13
+ <link rel="shortcut icon" href="../assets/favicon.png">
14
+ <link rel="apple-touch-icon" href="../assets/shopify-57.png">
15
+ <link rel="apple-touch-icon" sizes="72x72" href="../assets/shopify-72.png">
16
+ <link rel="apple-touch-icon" sizes="114x114" href="../assets/shopify-114.png">
17
+
18
+ <!-- Le HTML5 shim, for IE6-8 support of HTML elements -->
19
+ <!--[if lt IE 9]>
20
+ <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
21
+ <![endif]-->
22
+ </head>
23
+
24
+ <body>
25
+
26
+ <div class="navbar navbar-fixed-top">
27
+ <div class="navbar-inner">
28
+ <div class="container">
29
+
30
+ <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
31
+ <span class="icon-bar"></span>
32
+ <span class="icon-bar"></span>
33
+ <span class="icon-bar"></span>
34
+ </a>
35
+
36
+ <%= link_to 'Shopify Demo App', '/', :class => 'brand' %>
37
+
38
+ <% if shop_session %>
39
+ <div class="nav-collapse">
40
+ <ul class="nav">
41
+ <li class='<%= active_nav_class('home', 'index') %>'><%= link_to 'Where to Start', '/' %></li>
42
+ <li class='<%= active_nav_class('home', 'design') %>'><%= link_to 'Bootstrap Info', '/design' %></li>
43
+ </ul>
44
+ </div>
45
+
46
+ <ul class="nav pull-right">
47
+ <li class="dropdown">
48
+ <%= link_to raw(shop_session.url+' <b class="caret"></b>'), "https://#{shop_session.url}", :class => 'shop_name dropdown-toggle', :'data-toggle' => 'dropdown', :'data-target' => '#' %>
49
+ <ul class="dropdown-menu">
50
+ <li><%= link_to raw('<i class="icon-home"></i> Storefront'), "http://"+shop_session.url, :target => 'blank' %></li>
51
+ <li><%= link_to raw('<i class="icon-cog"></i> Shopify Admin'), "http://"+shop_session.url+"/admin", :target => 'blank' %></li>
52
+ <li class="divider"></li>
53
+ <li><%= link_to raw('<i class="icon-off"></i> Logout'), logout_path, :method => :delete %></li>
54
+ </ul>
55
+ </li>
56
+ </ul>
57
+ <% end %>
58
+
59
+ </div>
60
+ </div>
61
+ </div>
62
+
63
+
64
+ <div class="container">
65
+ <% flash.each do |type, message| %>
66
+ <div class="alert"><%= message %></div>
67
+ <% end %>
68
+
69
+ <div class="content">
70
+ <%= yield %>
71
+ </div>
72
+
73
+ <footer>
74
+ <p>A Shopify app by (company name here)</p>
75
+ </footer>
76
+
77
+ </div> <!-- /container -->
78
+ </body>
79
+ </html>
@@ -0,0 +1,21 @@
1
+ <div class="page-header" id="login-header">
2
+ <h1>Install This App</h1>
3
+ <h1><small>This app requires you to login to start using it.</small></h1>
4
+ </div>
5
+
6
+ <div style="width:340px; margin:0 auto;">
7
+ <%= form_tag login_path, :class => 'form-search' do %>
8
+ <%= text_field_tag 'shop', nil, :placeholder => 'Shop URL', :class => 'btn-large' %>
9
+ <%= submit_tag 'Install', :class => 'btn btn-primary btn-large' %>
10
+ <% end %>
11
+ </div>
12
+
13
+ <p align="center" style="margin-top:30px">
14
+ <%= image_tag 'shopify.png' %>
15
+ </p>
16
+
17
+ <br/>
18
+
19
+ <p align="center" class="muted">
20
+ Don't have a shop? <a href="https://app.shopify.com/services/partners/api_clients/test_shops">Create a Test Shop</a>
21
+ </p>
@@ -0,0 +1,14 @@
1
+ Rails.application.config.middleware.use OmniAuth::Builder do
2
+ provider :shopify,
3
+ ShopifyApp.configuration.api_key,
4
+ ShopifyApp.configuration.secret,
5
+
6
+ # Example permission scopes - see http://docs.shopify.com/api/tutorials/oauth for full listing
7
+ :scope => 'read_orders, read_products',
8
+
9
+ :setup => lambda {|env|
10
+ params = Rack::Utils.parse_query(env['QUERY_STRING'])
11
+ site_url = "https://#{params['shop']}"
12
+ env['omniauth.strategy'].options[:client_options][:site] = site_url
13
+ }
14
+ end
@@ -0,0 +1,21 @@
1
+ # You should replace InMemorySessionStore with what you will be using
2
+ # in Production
3
+ #
4
+ # Interface to implement are self.retrieve(id) and self.store(ShopifyAPI::Session)
5
+ #
6
+ # Here is how you would add these functions to an ActiveRecord:
7
+ #
8
+ # class Shop < ActiveRecord::Base
9
+ # def self.store(session)
10
+ # shop = Shop.new(domain: session.url, token: session.token)
11
+ # shop.save!
12
+ # shop.id
13
+ # end
14
+ #
15
+ # def self.retrieve(id)
16
+ # shop = Shop.find(id)
17
+ # ShopifyAPI::Session.new(shop.domain, shop.token)
18
+ # end
19
+ # end
20
+
21
+ ShopifySessionRepository.storage = InMemorySessionStore
@@ -0,0 +1,40 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>404 Error: This page doesn't exist!</title>
5
+
6
+ <style>
7
+ .container { text-align:center;}
8
+ .navbar .brand { float:none;}
9
+ </style>
10
+ </head>
11
+
12
+ <body>
13
+ <div class="navbar navbar-fixed-top">
14
+ <div class="navbar-inner">
15
+ <div class="container">
16
+ <a href="/" class="brand">Shopify Demo App</a>
17
+ </div>
18
+ </div>
19
+ </div>
20
+
21
+ <div class="container">
22
+ <div class="content">
23
+ <div class="page-header">
24
+ <h1>AH! 404!</h1>
25
+ </div>
26
+
27
+ <h3><i class="icon-warning-sign" style="margin-top:6px; opacity:.5;"></i> Well dang, looks like this page doesn't exist.</h3>
28
+ <p class="muted">Well, not this one, but the one you were looking for... at least there's a kitten!</p>
29
+ <br/>
30
+ <p><img src="http://gifs.gifbin.com/122009/1259928856_surprised_kitten.gif" style="border-radius:10px;"/></p>
31
+ <br/>
32
+ <p><button type="button" value ="back" onClick="window.history.back();" class='btn btn-primary'><i class="icon-chevron-left" style="opacity:.25"></i> Back to the app</button></p>
33
+ </div>
34
+
35
+ <footer>
36
+ <p>A Shopify app by (company name here)</p>
37
+ </footer>
38
+ </div> <!-- /container -->
39
+ </body>
40
+ </html>