├── .gitignore
├── .travis.yml
├── README.md
├── package.json
├── rollup.config.js
├── src
├── index.css
└── index.js
└── static
├── 404.html
├── icons
├── android-chrome-192x192.png
├── android-chrome-512x512.png
├── apple-touch-icon.png
└── favicon.png
├── index.html
├── manifest.json
└── sw.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | static/index.js
3 | yarn.lock
4 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "7"
4 |
5 | script: npm run build
6 |
7 | deploy:
8 | fqdn: hyperapp-pwa.deployable.site
9 | local_dir: static
10 | provider: pages
11 | skip_cleanup: true
12 | github_token: $GITHUB_TOKEN
13 | on:
14 | branch: master
15 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # hyperapp-pwa
2 | > A minimalist _progressive web app_ compliant template for hyperapp projects
3 |
4 | Once you have cloned or forked this project, use the following tasks from the project root:
5 |
6 | ```
7 | npm install // Install all dependencies
8 | npm start // Serve app on localhost and watch source files
9 | ```
10 |
11 | This will build the application and serve it on http://localhost:8080
12 |
13 | **DEMO:** https://hyperapp-pwa.deployable.site
14 |
15 | ## Features of this template
16 |
17 | - Very minimal config files, developer and client side dependencies
18 | - Developer task that rebuilds app when source files change using [rollup-watch](https://www.npmjs.com/package/rollup-watch)
19 | - Reloads the browser when source files change using [rollup-plugin-livereload](https://www.npmjs.com/package/rollup-plugin-livereload)
20 | - Bundle scripts supporting `ES6` and `JSX` transforms using [buble](https://www.npmjs.com/package/buble)
21 | - Preprocessing and concatenating stylesheets using using [rollup-plugin-postcss](https://www.npmjs.com/package/rollup-plugin-postcss)
22 | - Local static file server supporting HTML5 fallback using [rollup-plugin-server](https://www.npmjs.com/package/rollup-plugin-server)
23 | - Frontend application state management and routing using [hyperapp](https://www.npmjs.com/package/hyperapp)
24 | - PWA compliant resources; service worker, manifest and icons passing [lighthouse](https://github.com/GoogleChrome/lighthouse)
25 | - Static deploys to `gh-pages` when merged to master using [TravisCI](https://travis-ci.org/)
26 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "1.0.0",
3 | "name": "hyperapp-pwa",
4 | "description": "A ready-to-deploy progressive web app starter",
5 | "author": "Luke Jackson (lukejacksonn@gmail.com)",
6 | "license": "MIT",
7 | "main": "src/index.js",
8 | "scripts": {
9 | "build": "rollup -c",
10 | "start": "rollup -c -w"
11 | },
12 | "devDependencies": {
13 | "postcss-nested": "^2.1.2",
14 | "rollup": "^0.49.2",
15 | "rollup-plugin-buble": "^0.15.0",
16 | "rollup-plugin-commonjs": "^8.2.0",
17 | "rollup-plugin-livereload": "^0.6.0",
18 | "rollup-plugin-node-resolve": "^3.0.0",
19 | "rollup-plugin-postcss": "^0.5.4",
20 | "rollup-plugin-serve": "^0.4.2",
21 | "rollup-plugin-uglify": "^2.0.1"
22 | },
23 | "dependencies": {
24 | "hyperapp": "^1.0.1"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import buble from 'rollup-plugin-buble'
2 | import commonjs from 'rollup-plugin-commonjs'
3 | import resolve from 'rollup-plugin-node-resolve'
4 | import uglify from 'rollup-plugin-uglify'
5 | import serve from 'rollup-plugin-serve'
6 | import livereload from 'rollup-plugin-livereload'
7 | import postcss from 'rollup-plugin-postcss'
8 | import nested from 'postcss-nested'
9 |
10 | const prod = !process.env.ROLLUP_WATCH
11 | const dev = !!process.env.ROLLUP_WATCH
12 |
13 | export default {
14 | input: 'src/index.js',
15 | output: {
16 | file: 'static/index.js',
17 | sourcemap: dev ? 'inline' : false,
18 | format: 'iife',
19 | intro:
20 | !dev &&
21 | `
22 | history.replaceState(null, null, sessionStorage.redirect)
23 | delete sessionStorage.redirect
24 | if ('serviceWorker' in navigator) navigator.serviceWorker.register('/sw.js')
25 | `,
26 | },
27 | plugins: [
28 | postcss({ plugins: [nested()] }),
29 | resolve({ jsnext: true }),
30 | buble({ jsx: 'h' }),
31 | commonjs(),
32 | buble(),
33 | prod && uglify(),
34 | dev && livereload('static'),
35 | dev &&
36 | serve({
37 | contentBase: ['static'],
38 | historyApiFallback: true,
39 | port: 8080,
40 | }),
41 | ],
42 | }
43 |
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | html {
2 | font-size: calc(8px + 2vmin);
3 | font-family: sans-serif;
4 | background: white;
5 | }
6 |
7 | body,
8 | body * {
9 | display: block;
10 | background: none;
11 | box-sizing: border-box;
12 | margin: 0;
13 | border: 0;
14 | padding: 0;
15 | outline: 0;
16 | }
17 |
18 | body,
19 | noscript {
20 | height: 100vh;
21 | display: flex;
22 | align-items: center;
23 | justify-content: center;
24 | }
25 |
26 | div {
27 | display: flex;
28 | > * + * {
29 | margin-left: 0.38rem;
30 | }
31 | }
32 |
33 | noscript {
34 | width: 100vw;
35 | align-items: center;
36 | justify-content: center;
37 | font-weight: bold;
38 | }
39 |
40 | button {
41 | padding: 0.62rem 1rem;
42 | font-size: 0.62rem;
43 | border: 1px solid #000;
44 | font-weight: bold;
45 | cursor: pointer;
46 | touch-action: manipulation;
47 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
48 | }
49 |
50 | h1 {
51 | margin: auto;
52 | font-size: 8rem;
53 | cursor: pointer;
54 | text-align: center;
55 | }
56 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import { app, h } from 'hyperapp'
2 | import './index.css'
3 |
4 | const state = {
5 | count: 0,
6 | }
7 |
8 | const actions = {
9 | reset: () => ({ count: 0 }),
10 | sum: data => ({ count }) => ({ count: count + data }),
11 | }
12 |
13 | const view = (state, actions) => (
14 | {state.count}
16 |