├── .gitignore ├── public ├── favicon.ico ├── sw.js ├── index.html └── src │ ├── js │ └── app.js │ └── css │ └── app.css ├── package.json └── README.MD /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | node_modules 3 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/academind/pwa-sneak-peak/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pwa-complete-guide", 3 | "version": "1.0.0", 4 | "description": "A complete guide to PWAs. Building a simple Instagram clone.", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "http-server -c-1 -p 3000" 8 | }, 9 | "keywords": [ 10 | "pwa", 11 | "progressive", 12 | "web", 13 | "app", 14 | "complete", 15 | "tutorial" 16 | ], 17 | "author": "Maximilian Schwarzmüller", 18 | "license": "ISC", 19 | "devDependencies": { 20 | "http-server": "^0.10.0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /public/sw.js: -------------------------------------------------------------------------------- 1 | self.addEventListener('install', function(event) { 2 | event.waitUntil( 3 | caches.open('first-app') 4 | .then(function(cache) { 5 | cache.addAll([ 6 | '/', 7 | '/index.html', 8 | '/src/css/app.css', 9 | '/src/js/app.js' 10 | ]) 11 | }) 12 | ); 13 | }); 14 | 15 | self.addEventListener('fetch', function(event) { 16 | event.respondWith( 17 | caches.match(event.request) 18 | .then(function(res) { 19 | return res; 20 | }) 21 | ); 22 | }); -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | # Progressive Web Apps - Complete Guide 2 | This source code is part of Maximilian Schwarzmüller's "Progressive Web Apps - Complete Guide" course on udemy.com. 3 | 4 | # How to Use 5 | You need [Node.js](https://nodejs.org) installed on your machine. Simply download the installer from [nodejs.org](https://nodejs.org) and go through the installation steps. 6 | 7 | Once Node.js is installed, open your command prompt or terminal and **navigate into this project folder**. There, run `npm install` to install all required dependencies. 8 | 9 | Finally, run `npm start` to start the development server and visit [localhost:3000](http://localhost:3000) to see the running application. 10 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | Progressive Web Apps 9 | 10 | 11 | 12 |
13 |

Progressive Web Apps

14 |
15 |
16 |
17 |

They're installable (without an App Store)!

18 |
19 |
20 |

They can work offline!

21 |
22 |
23 |

They look good on any device

24 |
25 |
26 |

You can receive Push Messages...

27 |
28 |
29 |

...and show Notifications

30 |
31 |
32 |

PWAs can access native device features like the Camera

33 |
34 |
35 |

And so much more!

36 |
37 |
38 |
39 | 40 |
41 | 42 | 43 | -------------------------------------------------------------------------------- /public/src/js/app.js: -------------------------------------------------------------------------------- 1 | var title = document.querySelector('.title'); 2 | var courseFeatureElements = document.querySelectorAll('.course-feature'); 3 | var button = document.querySelector('button'); 4 | 5 | function animate() { 6 | title.classList.remove('animate-in'); 7 | for (var i = 0; i < courseFeatureElements.length; i++) { 8 | courseFeatureElements[i].classList.remove('animate-in'); 9 | } 10 | button.classList.remove('animate-in'); 11 | 12 | setTimeout(function () { 13 | title.classList.add('animate-in'); 14 | }, 1000); 15 | 16 | setTimeout(function () { 17 | courseFeatureElements[0].classList.add('animate-in'); 18 | }, 3000); 19 | 20 | setTimeout(function () { 21 | courseFeatureElements[1].classList.add('animate-in'); 22 | }, 4500); 23 | 24 | setTimeout(function () { 25 | courseFeatureElements[2].classList.add('animate-in'); 26 | }, 6000); 27 | 28 | setTimeout(function () { 29 | courseFeatureElements[3].classList.add('animate-in'); 30 | }, 7500); 31 | 32 | setTimeout(function () { 33 | courseFeatureElements[4].classList.add('animate-in'); 34 | }, 9000); 35 | 36 | setTimeout(function () { 37 | courseFeatureElements[5].classList.add('animate-in'); 38 | }, 10500); 39 | 40 | setTimeout(function () { 41 | courseFeatureElements[6].classList.add('animate-in'); 42 | }, 12000); 43 | 44 | setTimeout(function () { 45 | button.classList.add('animate-in'); 46 | }, 13500); 47 | } 48 | 49 | animate(); 50 | 51 | button.addEventListener('click', function() { 52 | animate(); 53 | }); -------------------------------------------------------------------------------- /public/src/css/app.css: -------------------------------------------------------------------------------- 1 | body, html { 2 | margin: 0; 3 | font-family: Arial, sans-serif; 4 | } 5 | 6 | .animate-in { 7 | animation: fade-slide 1.5s forwards; 8 | } 9 | 10 | .title { 11 | width: 100%; 12 | background-color: #ccc; 13 | text-align: center; 14 | padding: 30px 0; 15 | } 16 | 17 | .title h1 { 18 | margin: 0; 19 | color: white; 20 | font-size: 1.8em; 21 | } 22 | 23 | .title, .course-feature { 24 | opacity: 0; 25 | } 26 | 27 | .content, .start-over { 28 | margin: 5px auto; 29 | text-align: center; 30 | width: 80%; 31 | max-width: 500px; 32 | } 33 | 34 | .course-feature { 35 | padding: 2px; 36 | -webkit-box-shadow: 2px 2px 1px #ccc; 37 | -moz-box-shadow: 2px 2px 1px #ccc; 38 | box-shadow: 2px 2px 1px #ccc; 39 | } 40 | 41 | .course-feature { 42 | margin: 10px auto; 43 | } 44 | 45 | #installable { 46 | background-color: #d3ff7b; 47 | } 48 | 49 | #offline { 50 | background-color: #9ce9ff; 51 | } 52 | 53 | #responsive { 54 | background-color: #ffaf8a; 55 | } 56 | 57 | #push { 58 | background-color: #fff395; 59 | } 60 | 61 | #notifications { 62 | background-color: #ffcedf; 63 | } 64 | 65 | #native-features { 66 | background-color: #ddb5ff; 67 | } 68 | 69 | #more { 70 | background-color: #afffc3; 71 | } 72 | 73 | .start-over button { 74 | background-color: #fa923f; 75 | border: 1px solid #fa923f; 76 | -webkit-box-shadow: 2px 2px 2px #ccc; 77 | -moz-box-shadow: 2px 2px 2px #ccc; 78 | box-shadow: 2px 2px 2px #ccc; 79 | padding: 5px; 80 | color: white; 81 | opacity: 0; 82 | cursor: pointer; 83 | outline: none; 84 | } 85 | 86 | .start-over button:hover { 87 | background-color: #ff7f16; 88 | } 89 | 90 | @keyframes fade-slide { 91 | 0% { 92 | opacity: 0; 93 | transform: translateY(50px); 94 | } 95 | 96 | 100% { 97 | opacity: 1; 98 | transform: translateY(0); 99 | } 100 | } --------------------------------------------------------------------------------