├── .babelrc.js
├── .browserslistrc
├── .codeclimate.yml
├── .editorconfig
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── .huskyrc
├── .netlify
└── state.json
├── .nvmrc
├── .stylelintignore
├── .stylelintrc
├── .vscode
└── settings.json
├── LICENSE
├── README.md
├── gulpfile.babel.js
├── package.json
├── postcss.config.js
├── site-config.json
├── source
├── components
│ ├── buttons
│ │ ├── button.js
│ │ ├── button.scss
│ │ └── buttons.pug
│ └── hero
│ │ ├── hero.js
│ │ ├── hero.pug
│ │ └── hero.scss
├── images
│ ├── icon-white.png
│ ├── icon-white.svg
│ ├── icon.png
│ ├── icon.sketch
│ └── share.jpg
├── index.js
├── index.pug
├── layouts
│ ├── _favicons.pug
│ ├── _head.pug
│ ├── _metas.pug
│ ├── _scripts.pug
│ └── default.pug
├── static
│ ├── _redirects
│ ├── humans.txt
│ └── robots.txt
└── styles
│ ├── _base.scss
│ ├── _mixins.scss
│ ├── _vars.scss
│ └── main.scss
├── tasks
├── build.js
├── config
│ ├── base.js
│ ├── index.js
│ ├── paths.js
│ ├── plugins.js
│ └── webpack.js
├── favicons.js
├── index.js
├── static.js
└── watch.js
└── yarn.lock
/.babelrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@babel/preset-env'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 1 version
3 | maintained node versions
4 | not dead
5 |
--------------------------------------------------------------------------------
/.codeclimate.yml:
--------------------------------------------------------------------------------
1 | version: '2'
2 |
3 | plugins:
4 | eslint:
5 | enabled: true
6 | channel: 'eslint-5'
7 | config:
8 | config: .eslintrc.js
9 |
10 | checks:
11 | method-complexity:
12 | enabled: false
13 | method-lines:
14 | config:
15 | threshold: 150
16 | similar-code:
17 | enabled: false
18 | identical-code:
19 | enabled: false
20 |
21 | ratings:
22 | paths:
23 | - '**.js'
24 | - '**.scss'
25 |
26 | exclude_paths:
27 | - .vscode/**/*
28 | - .netlify/**/*
29 | - dist/**/*
30 | - source/img/**/*
31 | - source/static/**/*
32 | - source/scss/clean-admin/**/*
33 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 |
12 | # The JSON files contain newlines inconsistently
13 | [*.json]
14 | insert_final_newline = ignore
15 |
16 | # Minified JavaScript files shouldn't be changed
17 | [**.min.js]
18 | indent_style = ignore
19 | insert_final_newline = ignore
20 |
21 | [*.md]
22 | trim_trailing_whitespace = false
23 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | dist
2 | __src
3 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: 'standard',
3 | env: {
4 | browser: true,
5 | es6: true,
6 | jquery: true
7 | },
8 | globals: {
9 | "$": true,
10 | "jQuery": true,
11 | "fetch": true,
12 | "window": true,
13 | "document": true
14 | },
15 | rules: {
16 | 'quote-props': 'off',
17 | 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
18 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (https://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # Typescript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 |
60 | dist
61 | __src
62 | source/components/**/*.json
63 |
--------------------------------------------------------------------------------
/.huskyrc:
--------------------------------------------------------------------------------
1 | {
2 | "hooks": {
3 | "pre-commit": "npm run lint"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/.netlify/state.json:
--------------------------------------------------------------------------------
1 | {
2 | "siteId": "59489b42-daeb-4c07-af4a-158aae7ff899"
3 | }
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | 10
--------------------------------------------------------------------------------
/.stylelintignore:
--------------------------------------------------------------------------------
1 | **/*.css
2 |
--------------------------------------------------------------------------------
/.stylelintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "stylelint-config-sass-guidelines",
3 | "rules": {
4 | "indentation": 2,
5 | "max-nesting-depth": 3,
6 | "number-leading-zero": null,
7 | "at-rule-empty-line-before": null,
8 | "no-descending-specificity": null,
9 | "scss/dollar-variable-pattern": null
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "eslint.autoFixOnSave": true,
3 | "eslint.alwaysShowStatus": true,
4 | "eslint.enable": true,
5 | "stylelint.enable": true,
6 | "css.validate": false,
7 | "scss.validate": true,
8 | "files.exclude": {
9 | "**/node_modules": false
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 OneDev studio
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # [Starter Kit](https://starter-kit.nandomoreira.dev/)
2 |
3 | [](https://codeclimate.com/github/onedevstudio/starter-kit/maintainability)    [](https://app.netlify.com/sites/starter-kit/deploys)
4 |
5 | > A simple and powerful Starter Kit made with Webpack, Gulp 4, Pug and SASS
6 |
7 | ## Table of Contents
8 |
9 | - [Installation](#installation)
10 | - [Support](#support)
11 | - [Contributing](#contributing)
12 | - [Tasks](#tasks)
13 | - [History](#history)
14 | - [License](#license)
15 |
16 | ## Installation
17 |
18 | ```bash
19 | git clone https://github.com/onedevstudio/starter-kit.git your-project
20 | cd your-project/ && rm -rf .git
21 | yarn install # or npm install
22 | yarn dev # or npm run dev
23 | ```
24 |
25 | ## Support
26 |
27 | Please [open an issue](../../issues/new) for support.
28 |
29 | ## Contributing
30 |
31 | Please contribute using [Github Flow](https://guides.github.com/introduction/flow/). Create a branch, add commits, and [open a pull request](../../compare?expand=1).
32 | Contributing
33 |
34 | 1. Fork it!
35 | 2. Create your feature branch: git checkout -b my-new-feature
36 | 3. Commit your changes: git commit -m 'Add some feature'
37 | 4. Push to the branch: git push origin my-new-feature
38 | 5. Submit a pull request :D
39 |
40 | ## Tasks
41 |
42 | **Gulp tasks**
43 |
44 | - `gulp` ~> Build and watch files
45 | - `gulp watch` ~> Watch js files
46 | - `gulp server` ~> Watch js files and start browser sync server
47 | - `gulp copyFiles` ~> Copy static files
48 | - `gulp favicons` ~> Generate all favicons
49 | - `gulp build` ~> Build all files
50 |
51 | **NPM scripts**
52 |
53 | - `npm run start` ~> Starts the task `gulp server` in env production
54 | - `npm run prod` ~> Starts the tasks `npm run lint` and `npm run build`
55 | - `npm run build` ~> Starts the tasks `gulp build` in env production
56 | - `npm run dev` ~> Starts the tasks `gulp` in env development
57 | - `npm run deploy` ~> Starts the tasks `npm run prod` and run the command `netlify deploy --prod`
58 | - `npm run eslint` ~> Run the command `eslint .`
59 | - `npm run eslint:fix` ~> Run the task `npm run eslint --fix`
60 | - `npm run stylelint` ~> Run the command `stylelint "**/*.scss"`
61 | - `npm run stylelint:fix` ~> Run the task `npm run stylelint --fix`
62 | - `npm run lint` ~> Starts the tasks `npm run eslint` and `npm run stylelint`
63 | - `npm run pre-commit` ~> Start the task `npm run lint`
64 |
65 | ## History
66 |
67 | See [Releases](../../releases) for detailed changelog.
68 |
69 | ## Author
70 |
71 | | [](http://twitter.com/oseunando "Follow @oseunando on Twitter") |
72 | | ----------------------------------------------------------------------------------------------------------------------------------------------- |
73 | | [Fernando Moreira](http://twitter.com/oseunando) |
74 |
75 | ## License
76 |
77 | ```
78 | WWWWWW||WWWWWW
79 | W W W||W W W
80 | ||
81 | ( OO )__________
82 | / | \
83 | /o o| MIT \
84 | \___/||_||__||_|| *
85 | || || || ||
86 | _||_|| _||_||
87 | (__|__|(__|__|
88 | ```
89 |
90 | Code is under [MIT License](/LICENSE) - © Fernando Moreira
91 |
92 | ## Buy me a coffee?
93 |
94 | It will encourage me to keep it going, fix whatever bugs you find and spend time making it better :D
95 |
96 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/gulpfile.babel.js:
--------------------------------------------------------------------------------
1 | import defaultTask from './tasks'
2 |
3 | export * from './tasks' // eslint-disable-line
4 |
5 | export default defaultTask
6 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "starter-kit",
3 | "version": "2.4.0",
4 | "title": "Starter Kit",
5 | "description": "A simple and powerful Starter Kit made with Webpack, Gulp 4, Pug and SASS",
6 | "homepage": "https://starter-kit.nandomoreira.dev",
7 | "main": "gulpfile.babel.js",
8 | "scripts": {
9 | "start": "NODE_ENV=production gulp server",
10 | "prod": "npm run lint && npm run build",
11 | "build": "NODE_ENV=production gulp build",
12 | "dev": "NODE_ENV=development gulp",
13 | "deploy": "npm run prod && npm run deploy:netlify",
14 | "deploy:netlify": "netlify deploy --prod --message \"Deploy with netlify command line\"",
15 | "eslint": "eslint .",
16 | "eslint:fix": "npm run eslint --fix",
17 | "stylelint": "stylelint \"./source/styles/**/*.scss\"",
18 | "stylelint:fix": "npm run stylelint --fix",
19 | "lint": "npm run eslint && npm run stylelint",
20 | "pre-commit": "npm run lint",
21 | "test": "echo 'no has test! lol'"
22 | },
23 | "repository": {
24 | "type": "git",
25 | "url": "https://github.com/onedevstudio/starter-kit"
26 | },
27 | "keywords": [
28 | "starter-kit",
29 | "starter",
30 | "kit",
31 | "babel",
32 | "es6",
33 | "stylus",
34 | "gulp",
35 | "gulpjs"
36 | ],
37 | "author": {
38 | "name": "Fernando Moreira",
39 | "email": "nandomoreira.me@gmail.com",
40 | "site": "https://nandomoreira.dev",
41 | "twitter": "oseunando"
42 | },
43 | "license": "MIT",
44 | "bugs": {
45 | "url": "https://github.com/onedevstudio/starter-kit/issues"
46 | },
47 | "engines": {
48 | "node": ">=10"
49 | },
50 | "dependencies": {},
51 | "devDependencies": {
52 | "@babel/cli": "^7.5.5",
53 | "@babel/core": "^7.5.5",
54 | "@babel/plugin-proposal-object-rest-spread": "^7.5.5",
55 | "@babel/preset-env": "^7.5.5",
56 | "@babel/register": "^7.5.5",
57 | "autoprefixer": "^9.6.1",
58 | "babel-loader": "^8.0.6",
59 | "browser-sync": "^2.26.7",
60 | "clean-webpack-plugin": "^3.0.0",
61 | "css-loader": "^3.2.0",
62 | "cssnano": "^4.1.10",
63 | "dotenv": "^8.1.0",
64 | "eslint": "^6.2.2",
65 | "eslint-config-standard": "^13.0.1",
66 | "eslint-plugin-import": "^2.18.2",
67 | "eslint-plugin-node": "^9.1.0",
68 | "eslint-plugin-promise": "^4.2.1",
69 | "eslint-plugin-standard": "^4.0.1",
70 | "favicons": "^5.4.1",
71 | "file-loader": "^4.2.0",
72 | "gulp": "^4.0.2",
73 | "gulp-size": "^3.0.0",
74 | "gulp-util": "^3.0.8",
75 | "html-webpack-plugin": "^3.2.0",
76 | "husky": "^3.0.4",
77 | "lost": "^8.3.1",
78 | "mini-css-extract-plugin": "^0.8.0",
79 | "netlify-cli": "^2.12.0",
80 | "node-sass": "^4.12.0",
81 | "offline-plugin": "^5.0.7",
82 | "postcss-font-magician": "^2.2.2",
83 | "postcss-loader": "^3.0.0",
84 | "postcss-modules": "^1.4.1",
85 | "pug": "^2.0.4",
86 | "pug-loader": "^2.4.0",
87 | "rucksack-css": "^1.0.2",
88 | "sass-loader": "^7.3.1",
89 | "style-loader": "^0.23.1",
90 | "stylelint": "^10.1.0",
91 | "stylelint-config-sass-guidelines": "^6.0.0",
92 | "stylelint-config-standard": "^18.3.0",
93 | "webpack": "^4.39.2",
94 | "webpack-dev-middleware": "^3.7.0",
95 | "webpack-hot-middleware": "^2.25.0"
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs')
2 | const {
3 | dirname,
4 | basename,
5 | resolve
6 | } = require('path')
7 |
8 | module.exports = {
9 | plugins: {
10 | 'rucksack-css': {},
11 | 'lost': {},
12 | 'postcss-font-magician': {},
13 | 'autoprefixer': {},
14 | 'cssnano': {
15 | add: true
16 | },
17 | 'postcss-modules': {
18 | getJSON (cssFileName, json) {
19 | const isComponent = /components/.test(dirname(cssFileName))
20 |
21 | if (isComponent) {
22 | const cssName = basename(`${cssFileName}`)
23 | const jsonFileName = resolve(`${dirname(cssFileName)}/${cssName.split('.')[0]}-css.json`)
24 | fs.writeFileSync(jsonFileName, JSON.stringify(json))
25 | }
26 | }
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/site-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "lang": "en-US",
3 | "locale": "en_US",
4 | "icon": "images/icon.png",
5 | "theme_color": "#0b7ff5",
6 | "ga": "UA-125092358-6"
7 | }
8 |
--------------------------------------------------------------------------------
/source/components/buttons/button.js:
--------------------------------------------------------------------------------
1 | import './button.scss'
2 |
--------------------------------------------------------------------------------
/source/components/buttons/button.scss:
--------------------------------------------------------------------------------
1 | @import '../../styles/vars';
2 |
3 | .button {
4 | border: 0.125rem solid transparent;
5 | border-radius: 0.1875rem /* 3/16 */;
6 | color: #fff;
7 | cursor: pointer;
8 | display: inline-block;
9 | font-size: 1rem /* 16/16 */;
10 | font-weight: 500;
11 | letter-spacing: 0.05em;
12 | line-height: 2.375rem;
13 | margin: 0.625rem /* 10/16 */;
14 | padding: 0 0.75rem /* 12/16 */;
15 | text-align: center;
16 | text-decoration: none;
17 | transition: background-color 0.1s ease-in-out,
18 | border-color 0.1s ease-in-out,
19 | color 0.1s ease-in-out,
20 | box-shadow 0.1s ease-in-out,
21 | transform 0.1s ease-in-out;
22 | white-space: nowrap;
23 |
24 | span,
25 | svg {
26 | display: inline-block;
27 | margin: 0 0.3125rem /* 5/16 */;
28 | vertical-align: middle;
29 | }
30 |
31 | &:focus,
32 | &:active,
33 | &:hover {
34 | background-color: darken($primaryColor, 20%);
35 | border-color: darken($primaryColor, 20%);
36 | color: #fff;
37 | }
38 | }
39 |
40 | .primary {
41 | background-color: darken($primaryColor, 10%);
42 | border-color: darken($primaryColor, 10%);
43 | }
44 |
45 | .secondary {
46 | background-color: transparent;
47 | border-color: darken($primaryColor, 15%);
48 | }
49 |
--------------------------------------------------------------------------------
/source/components/buttons/buttons.pug:
--------------------------------------------------------------------------------
1 | - var css = require('./button-css.json');
2 |
3 | a(class=css.button + ' ' + css.primary href=globals.repository.url target='_blank')
4 | svg.icon.icon-github(xmlns='http://www.w3.org/2000/svg', width='22', height='22', viewbox='0 0 24 24', fill='none', stroke='currentColor', stroke-width='2', stroke-linecap='round', stroke-linejoin='round')
5 | path(d='M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22')
6 | span='Github Repo'
7 |
8 | a(class=css.button + ' ' + css.secondary href=globals.repository.url + '/releases/tag/v' + globals.version target='_blank')
9 | span='Download v' + globals.version
10 |
--------------------------------------------------------------------------------
/source/components/hero/hero.js:
--------------------------------------------------------------------------------
1 | import './hero.scss'
2 |
--------------------------------------------------------------------------------
/source/components/hero/hero.pug:
--------------------------------------------------------------------------------
1 | - var css = require('./hero-css.json');
2 |
3 | section(class=css.hero)
4 | div(class=css.hero__inner)
5 | span(class=css.hero__icon)
6 | img(src=require('../../images/icon-white.svg') alt=globals.title)
7 | h1(class=css.hero__title)
8 | =globals.title
9 | p(class=css.hero__description)
10 | ='{{ ' + globals.description + ' }}'
11 | div(class=css.hero__buttons)
12 | include ../buttons/buttons.pug
13 | footer(class=css.hero__footer)
14 | small
15 | ='Version: v' + globals.version + '. '
16 | ='developed by '
17 | a(href=globals.author.site + '?ref=' + globals.homepage target='_blank')
18 | =globals.author.name
19 |
--------------------------------------------------------------------------------
/source/components/hero/hero.scss:
--------------------------------------------------------------------------------
1 | @import '../../styles/vars';
2 | @import '../../styles/mixins';
3 |
4 | .hero {
5 | padding: 3.75rem /* 60/16 */ 0 1.25rem /* 20/16 */;
6 | text-align: center;
7 |
8 | @include media(min-width $breakpoint-md) {
9 | align-items: center;
10 | display: flex;
11 | height: 100vh;
12 | justify-content: center;
13 | padding: 0;
14 | }
15 |
16 | &__inner {
17 | max-width: 62.5rem /* 1000/16 */;
18 | padding: 0.9375rem /* 15/16 */;
19 | }
20 |
21 | &__icon {
22 | display: block;
23 | margin: 0;
24 |
25 | img {
26 | width: 6.25rem /* 100/16 */;
27 | }
28 | }
29 |
30 | &__title {
31 | font-size: 2.625rem /* 42/16 */;
32 | margin-bottom: 0.9375rem /* 15/16 */;
33 |
34 | @include media(min-width $breakpoint-sm) {
35 | font-size: 3.875rem /* 62/16 */;
36 | }
37 |
38 | @include media(min-width $breakpoint-md) {
39 | font-size: 4.5rem /* 72/16 */;
40 | }
41 | }
42 |
43 | &__description {
44 | color: rgba($textColor, .6);
45 | font-size: 1.125rem /* 18/16 */;
46 | font-weight: 300;
47 | margin-bottom: 1.875rem /* 30/16 */;
48 |
49 | @include media(min-width $breakpoint-md) {
50 | font-size: 1.375rem /* 22/16 */;
51 | }
52 | }
53 |
54 | &__buttons {
55 | a {
56 | display: inline-block;
57 | margin-bottom: 0.3125rem /* 5/16 */;
58 | width: 100%;
59 |
60 | @include media(min-width $breakpoint-sm) {
61 | margin-bottom: 0;
62 | width: auto;
63 | }
64 | }
65 | }
66 |
67 | &__footer {
68 | margin-top: 3.75rem /* 60/16 */;
69 | text-align: center;
70 | width: 100%;
71 |
72 | @include media(min-width $breakpoint-md) {
73 | bottom: 1.875rem /* 30/16 */;
74 | left: 50%;
75 | margin-top: 0;
76 | opacity: 0.75;
77 | position: fixed;
78 | transform: translate3d(-50%, 0, 0);
79 | }
80 |
81 | small {
82 | color: rgba($textColor, .6);
83 | }
84 |
85 | a {
86 | border-bottom: 1px solid $linkColor;
87 | font-weight: 700;
88 |
89 | &:hover {
90 | text-decoration: none;
91 | }
92 | }
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/source/images/icon-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/onedevstudio/starter-kit/4c255707d183ab8b65ac367d5184f0130c0114f2/source/images/icon-white.png
--------------------------------------------------------------------------------
/source/images/icon-white.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/source/images/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/onedevstudio/starter-kit/4c255707d183ab8b65ac367d5184f0130c0114f2/source/images/icon.png
--------------------------------------------------------------------------------
/source/images/icon.sketch:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/onedevstudio/starter-kit/4c255707d183ab8b65ac367d5184f0130c0114f2/source/images/icon.sketch
--------------------------------------------------------------------------------
/source/images/share.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/onedevstudio/starter-kit/4c255707d183ab8b65ac367d5184f0130c0114f2/source/images/share.jpg
--------------------------------------------------------------------------------
/source/index.js:
--------------------------------------------------------------------------------
1 | import * as offline from 'offline-plugin/runtime'
2 |
3 | import './styles/main.scss'
4 | import './components/hero/hero.js'
5 | import './components/buttons/button.js'
6 |
7 | offline.install({
8 | onUpdateReady: () => offline.applyUpdate()
9 | })
10 |
--------------------------------------------------------------------------------
/source/index.pug:
--------------------------------------------------------------------------------
1 | extends layouts/default.pug
2 | block content
3 | include components/hero/hero.pug
4 |
--------------------------------------------------------------------------------
/source/layouts/_favicons.pug:
--------------------------------------------------------------------------------
1 | link(rel='apple-touch-icon' sizes='114x114' href=globals.homepage + globals.favicons.path + 'apple-touch-icon-114x114.png')
2 | link(rel='apple-touch-icon' sizes='120x120' href=globals.homepage + globals.favicons.path + 'apple-touch-icon-120x120.png')
3 | link(rel='apple-touch-icon' sizes='144x144' href=globals.homepage + globals.favicons.path + 'apple-touch-icon-144x144.png')
4 | link(rel='apple-touch-icon' sizes='152x152' href=globals.homepage + globals.favicons.path + 'apple-touch-icon-152x152.png')
5 | link(rel='apple-touch-icon' sizes='180x180' href=globals.homepage + globals.favicons.path + 'apple-touch-icon-180x180.png')
6 | link(rel='apple-touch-icon' sizes='57x57' href=globals.homepage + globals.favicons.path + 'apple-touch-icon-57x57.png')
7 | link(rel='apple-touch-icon' sizes='60x60' href=globals.homepage + globals.favicons.path + 'apple-touch-icon-60x60.png')
8 | link(rel='apple-touch-icon' sizes='72x72' href=globals.homepage + globals.favicons.path + 'apple-touch-icon-72x72.png')
9 | link(rel='apple-touch-icon' sizes='76x76' href=globals.homepage + globals.favicons.path + 'apple-touch-icon-76x76.png')
10 | link(rel='apple-touch-startup-image' media='(device-width: 320px) and (device-height: 480px) and (-webkit-device-pixel-ratio: 1)' href=globals.homepage + globals.favicons.path + 'apple-touch-startup-image-320x460.png')
11 | link(rel='apple-touch-startup-image' media='(device-width: 320px) and (device-height: 480px) and (-webkit-device-pixel-ratio: 2)' href=globals.homepage + globals.favicons.path + 'apple-touch-startup-image-640x920.png')
12 | link(rel='apple-touch-startup-image' media='(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2)' href=globals.homepage + globals.favicons.path + 'apple-touch-startup-image-640x1096.png')
13 | link(rel='apple-touch-startup-image' media='(device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2)' href=globals.homepage + globals.favicons.path + 'apple-touch-startup-image-750x1294.png')
14 | link(rel='apple-touch-startup-image' media='(device-width: 414px) and (device-height: 736px) and (orientation: landscape) and (-webkit-device-pixel-ratio: 3)' href=globals.homepage + globals.favicons.path + 'apple-touch-startup-image-1182x2208.png')
15 | link(rel='apple-touch-startup-image' media='(device-width: 414px) and (device-height: 736px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 3)' href=globals.homepage + globals.favicons.path + 'apple-touch-startup-image-1242x2148.png')
16 | link(rel='apple-touch-startup-image' media='(device-width: 768px) and (device-height: 1024px) and (orientation: landscape) and (-webkit-device-pixel-ratio: 1)' href=globals.homepage + globals.favicons.path + 'apple-touch-startup-image-748x1024.png')
17 | link(rel='apple-touch-startup-image' media='(device-width: 768px) and (device-height: 1024px) and (orientation: landscape) and (-webkit-device-pixel-ratio: 2)' href=globals.homepage + globals.favicons.path + 'apple-touch-startup-image-1496x2048.png')
18 | link(rel='apple-touch-startup-image' media='(device-width: 768px) and (device-height: 1024px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 1)' href=globals.homepage + globals.favicons.path + 'apple-touch-startup-image-768x1004.png')
19 | link(rel='apple-touch-startup-image' media='(device-width: 768px) and (device-height: 1024px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 2)' href=globals.homepage + globals.favicons.path + 'apple-touch-startup-image-1536x2008.png')
20 | link(rel='icon' type='image/png' sizes='16x16' href=globals.homepage + globals.favicons.path + 'favicon-16x16.png')
21 | link(rel='icon' type='image/png' sizes='228x228' href=globals.homepage + globals.favicons.path + 'coast-228x228.png')
22 | link(rel='icon' type='image/png' sizes='32x32' href=globals.homepage + globals.favicons.path + 'favicon-32x32.png')
23 | link(rel='manifest' href=globals.homepage + globals.favicons.path + 'manifest.json')
24 | link(rel='shortcut icon' href=globals.homepage + globals.favicons.path + 'favicon.ico')
25 | link(rel='yandex-tableau-widget' href=globals.homepage + globals.favicons.path + 'yandex-browser-manifest.json')
26 | meta(name='apple-mobile-web-app-capable' content='yes')
27 | meta(name='apple-mobile-web-app-status-bar-style' content='black-translucent')
28 | meta(name='apple-mobile-web-app-title' content=globals.favicons.appName)
29 | meta(name='application-name' content=globals.favicons.appName)
30 | meta(name='mobile-web-app-capable' content='yes')
31 | meta(name='msapplication-TileColor' content=globals.favicons.background)
32 | meta(name='msapplication-TileImage' content=globals.homepage + globals.favicons.path + 'mstile-144x144.png')
33 | meta(name='msapplication-config' content=globals.homepage + globals.favicons.path + 'browserconfig.xml')
34 | meta(name='theme-color' content=globals.theme_color)
35 |
--------------------------------------------------------------------------------
/source/layouts/_head.pug:
--------------------------------------------------------------------------------
1 | head
2 | meta(charset='utf-8')
3 | meta(http-equiv='content-language' content=globals.lang)
4 | meta(name='viewport' content='width=device-width, initial-scale=1, maximum-scale=5')
5 | meta(http-equiv='X-UA-Compatible' content='IE=edge')
6 | link(rel='author', type='text/plain', href=globals.homepage + '/humans.txt')
7 |
8 | title=globals.title
9 |
10 | include ./_metas.pug
11 | include ./_favicons.pug
12 |
13 | if globals.isProduction
14 | script(async src='https://www.googletagmanager.com/gtag/js?id=' + globals.ga)
15 | script.
16 | window.dataLayer = window.dataLayer || [];
17 | function gtag(){dataLayer.push(arguments);}
18 | gtag('js', new Date());
19 | gtag('config', '#{globals.ga}');
20 |
--------------------------------------------------------------------------------
/source/layouts/_metas.pug:
--------------------------------------------------------------------------------
1 | meta(name='robots', content='index,follow')
2 | meta(http-equiv='cache-control', content='cache')
3 | meta(http-equiv='revisit-after', content='1 day')
4 |
5 | meta(name='application-name' content=globals.title)
6 | meta(property='og:title', content=globals.title)
7 | meta(name='twitter:title', content=globals.title)
8 |
9 | meta(name='description', content=globals.description)
10 | meta(property='og:description', content=globals.description)
11 | meta(itemprop='description', content=globals.description)
12 | meta(name='twitter:description', content=globals.description)
13 |
14 | - var image = globals.homepage + require('../images/share.jpg')
15 |
16 | meta(name='image' content=image)
17 | meta(itemprop='image' content=image)
18 | meta(property='og:image', content=image)
19 | meta(property='og:image:type', content='image/jpeg')
20 | meta(property='og:image:width', content='800')
21 | meta(property='og:image:height', content='600')
22 | meta(name='twitter:image:src', content=image)
23 | meta(name='twitter:card', content='summary_large_image')
24 |
25 | meta(name='mobile-web-app-capable' content='yes')
26 | meta(property='og:locale', content=globals.lang)
27 | meta(property='og:type', content='website')
28 | meta(property='og:url', content=globals.homepage)
29 | meta(property='og:site_name', content=globals.name)
30 | meta(itemprop='name', content=globals.name)
31 | meta(name='twitter:site', content='@' + globals.author.twitter)
32 | meta(name='twitter:creator', content='@' + globals.author.twitter)
33 | //- meta(property='fb:admins', content='Facebook numeric ID')
34 |
--------------------------------------------------------------------------------
/source/layouts/_scripts.pug:
--------------------------------------------------------------------------------
1 | block scripts
2 | script.
3 | // Block scripts
4 |
5 | if globals.isProduction
6 | script(type='text/javascript' src='//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-5c1eaed71a17af3a')
7 |
--------------------------------------------------------------------------------
/source/layouts/default.pug:
--------------------------------------------------------------------------------
1 | doctype html
2 | html(lang=globals.lang)
3 | include ./_head.pug
4 | body.layout-blank
5 | block content
6 | include ./_scripts.pug
7 |
--------------------------------------------------------------------------------
/source/static/_redirects:
--------------------------------------------------------------------------------
1 | # Redirect default Netlify subdomain to primary domain
2 | http://starter-kit.netlify.com/* http://starter-kit.nandomoreira.dev/:splat 301!
3 | https://starter-kit.netlify.com/* https://starter-kit.nandomoreira.dev/:splat 301!
4 |
--------------------------------------------------------------------------------
/source/static/humans.txt:
--------------------------------------------------------------------------------
1 | /* TEAM */
2 | Web developer: Fernando Moreira
3 | Site: https://nandomoreira.dev
4 | Email: nandomoreira.me [at] gmail.com
5 | Twitter: @oseunando
6 | From: Curitiba, Paraná, Brazil
7 |
8 | /* SITE */
9 | Language: English
10 | Doctype: HTML5
11 | IDE: Visual Studio Code
12 | Tech stack: Javascript, Webpack, Babel, HTML5, CSS3, SASS
13 |
--------------------------------------------------------------------------------
/source/static/robots.txt:
--------------------------------------------------------------------------------
1 | # Allow crawling of all content
2 | User-agent: *
3 | Disallow:
--------------------------------------------------------------------------------
/source/styles/_base.scss:
--------------------------------------------------------------------------------
1 | // Blocks
2 | html,
3 | body,
4 | p,
5 | ol,
6 | ul,
7 | li,
8 | dl,
9 | dt,
10 | dd,
11 | blockquote,
12 | figure,
13 | fieldset,
14 | legend,
15 | textarea,
16 | pre,
17 | iframe,
18 | hr,
19 | h1,
20 | h2,
21 | h3,
22 | h4,
23 | h5,
24 | h6 {
25 | margin: 0;
26 | padding: 0;
27 | }
28 |
29 | // List
30 | ul {
31 | list-style: none;
32 | }
33 |
34 | // Form
35 | button,
36 | input,
37 | select,
38 | textarea {
39 | margin: 0;
40 | }
41 |
42 | // Box sizing
43 | html {
44 | box-sizing: border-box;
45 | font-family: sans-serif;
46 | font-size: $fontSizeBase;
47 | /* stylelint-disable */
48 | -webkit-text-size-adjust: 100%;
49 | -ms-text-size-adjust: 100%;
50 | /* stylelint-enable */
51 | }
52 |
53 | *,
54 | *::before,
55 | *::after {
56 | box-sizing: inherit;
57 | }
58 |
59 | body {
60 | background-color: $backgroundColor;
61 | color: $textColor;
62 | font-family: $fontFamilyBase;
63 | font-size: 1rem /* 16/16 */;
64 | font-weight: $fontWeightBase;
65 | letter-spacing: -0.05px;
66 | line-height: $lineHeightBase;
67 | }
68 |
69 | // Headings
70 | h1,
71 | h2,
72 | h3,
73 | h4,
74 | h5,
75 | h6 {
76 | font-family: $fontFamilyHeading;
77 | font-size: 100%;
78 | font-weight: 800;
79 | margin: 0 0 1.875rem /* 30/16 */;
80 | }
81 |
82 | a {
83 | color: $linkColor;
84 | text-decoration: none;
85 |
86 | &:hover {
87 | color: $linkColorHover;
88 | text-decoration: underline;
89 | }
90 | }
91 |
92 | // Media
93 | img,
94 | embed,
95 | iframe,
96 | object,
97 | audio,
98 | video {
99 | height: auto;
100 | max-width: 100%;
101 | }
102 |
103 | // Iframe
104 | iframe {
105 | border: 0;
106 | }
107 |
108 | // Table
109 | table {
110 | border-collapse: collapse;
111 | border-spacing: 0;
112 | }
113 |
114 | td,
115 | th {
116 | padding: 0;
117 | text-align: left;
118 | }
119 |
120 | code,
121 | pre {
122 | font-family: $fontFamilyMonospace;
123 | font-size: 0.875rem /* 14/16 */;
124 | }
125 |
126 | pre {
127 | white-space: pre;
128 | white-space: pre-wrap;
129 | word-wrap: break-word;
130 | }
131 |
132 | small {
133 | font-size: 80%;
134 | }
135 |
136 | button,
137 | input,
138 | select,
139 | textarea {
140 | font-family: inherit;
141 | font-size: 100%;
142 | margin: 0;
143 | }
144 |
145 | textarea {
146 | vertical-align: top;
147 | }
148 |
149 | table {
150 | border-collapse: collapse;
151 | border-spacing: 0;
152 | }
153 |
154 | hr {
155 | border: 0;
156 | border-bottom: $borderBase;
157 | margin: 1.875rem /* 30/16 */ 0;
158 | }
159 |
--------------------------------------------------------------------------------
/source/styles/_mixins.scss:
--------------------------------------------------------------------------------
1 | /*
2 | Usage
3 |
4 | .container {
5 | width: 1200px;
6 |
7 | @include media(min-width 480px) {
8 | font-size: 1.2rem;
9 | }
10 |
11 | @include media(max-width 1200px) {
12 | width: 700px;
13 | }
14 | }
15 | */
16 |
17 | $default-feature: max-width;
18 |
19 | @mixin media($query: $feature $value) {
20 | @if length($query)==1 {
21 | @media screen and ($default-feature: nth($query, 1)) {
22 | @content;
23 | }
24 | }
25 |
26 | @else {
27 | $loop-to: length($query);
28 | $media-query: 'screen and ';
29 |
30 | @if length($query) % 2 !=0 {
31 | $loop-to: $loop-to - 1;
32 | }
33 |
34 | $i: 1;
35 |
36 | @while $i <=$loop-to {
37 | $media-query: $media-query + '('+ nth($query, $i) + ': '+ nth($query, $i + 1) + ') ';
38 |
39 | @if ($i + 1) !=$loop-to {
40 | $media-query: $media-query + 'and ';
41 | }
42 |
43 | $i: $i+2;
44 | }
45 |
46 | @media #{$media-query} {
47 | @content;
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/source/styles/_vars.scss:
--------------------------------------------------------------------------------
1 | // Color palette
2 | $blackColor: #000;
3 | $whiteColor: #fff;
4 | $greyColor: #5b5b5b;
5 | $silverColor: #d8d8d8;
6 | $primaryColor: #0b7ff5;
7 | // $textColor: lighten($blackColor, 15%);
8 | $textColor: $whiteColor;
9 | // $linkColor: $primaryColor;
10 | $linkColor: $whiteColor;
11 | $linkColorHover: lighten($linkColor, 10%);
12 | // $backgroundColor: darken($whiteColor, 2%);
13 | $backgroundColor: $primaryColor;
14 | $borderColor: rgba($blackColor, .1);
15 |
16 | $fontFamilyBase: 'Open Sans', -apple-system, system-ui, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
17 | $fontFamilyHeading: 'Poppins', $fontFamilyBase;
18 | $fontFamilySerif: 'Spectral', 'Georgia', 'Times New Roman', 'Times', serif;
19 | $fontFamilyMonospace: SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;
20 |
21 | $fontSizeBase: 16px;
22 | $lineHeightBase: 1.6;
23 | $fontWeightBase: 500;
24 | $letterSpacingBase: -0.05px;
25 |
26 | // Borders
27 | $borderBase: .0625rem /* 1/16 */ solid $borderColor;
28 | $borderRadiusBase: .25rem; /* 4/16 */
29 | $borderRadiusSmall: .125rem; /* 2/16 */
30 | $borderRadiusLarge: .375rem; /* 6/16 */
31 |
32 | $breakpoint-sm: 576px;
33 | $breakpoint-md: 768px;
34 | $breakpoint-lg: 992px;
35 | $breakpoint-xl: 1200px;
36 |
--------------------------------------------------------------------------------
/source/styles/main.scss:
--------------------------------------------------------------------------------
1 | @import 'vars';
2 | @import 'base';
3 |
--------------------------------------------------------------------------------
/tasks/build.js:
--------------------------------------------------------------------------------
1 | import webpack from 'webpack'
2 | import { series } from 'gulp'
3 | import { webpackConfig } from './config'
4 | import { favicons } from './favicons'
5 | import { copyFiles } from './static'
6 |
7 | const _webpack = () =>
8 | new Promise(resolve => webpack(webpackConfig, (err, stats) => {
9 | if (err) console.log('Webpack', err)
10 | console.log(stats.toString({ /* stats options */ }))
11 | resolve()
12 | }))
13 |
14 | const _task = series(_webpack, favicons, copyFiles)
15 | _task.description = '{{ build all scripts }}'
16 |
17 | export const build = _task
18 |
--------------------------------------------------------------------------------
/tasks/config/base.js:
--------------------------------------------------------------------------------
1 | require('dotenv').config()
2 |
3 | export const {
4 | NODE_ENV,
5 | DOTENV_CONFIG_EXAMPLE
6 | } = process.env
7 |
8 | const config = require('../../site-config.json')
9 | export const pkg = require('../../package.json')
10 |
11 | export const env = NODE_ENV || 'development'
12 | export const isProduction = env === 'production'
13 |
14 | export const homepage = isProduction ? pkg.homepage : 'http://localhost:3000'
15 | export const ga = isProduction ? config.ga : 'UA-000000000-1'
16 |
17 | delete pkg.main
18 | delete pkg.engines
19 | delete pkg.scripts
20 | delete pkg.dependencies
21 | delete pkg.devDependencies
22 |
23 | export const siteConfig = {
24 | ...pkg,
25 | ...{ env, isProduction, homepage },
26 | ...config,
27 | ...{ ga }
28 | }
29 |
--------------------------------------------------------------------------------
/tasks/config/index.js:
--------------------------------------------------------------------------------
1 | export * from './base'
2 | export * from './paths'
3 | export * from './plugins'
4 | export * from './webpack'
5 |
--------------------------------------------------------------------------------
/tasks/config/paths.js:
--------------------------------------------------------------------------------
1 | import { resolve, join } from 'path'
2 |
3 | const _rootPath = resolve(__dirname, '..', '..')
4 | const _srcPath = join(_rootPath, 'source')
5 | const _distPath = join(_rootPath, 'dist')
6 |
7 | export const paths = {
8 | root: _rootPath,
9 | modules: join(_rootPath, 'node_modules'),
10 | src: _srcPath,
11 | dist: _distPath,
12 | static: join(_srcPath, 'static'),
13 | components: join(_srcPath, 'components'),
14 | pages: join(_srcPath, 'pages'),
15 | styles: join(_srcPath, 'scss'),
16 | scripts: join(_srcPath, 'scripts')
17 | }
18 |
--------------------------------------------------------------------------------
/tasks/config/plugins.js:
--------------------------------------------------------------------------------
1 | import { isProduction, siteConfig } from './base'
2 | import { paths } from './paths'
3 |
4 | const plugins = {}
5 |
6 | plugins.size = require('gulp-size')
7 | plugins.favicons = require('favicons').stream
8 | plugins.browserSync = require('browser-sync').create()
9 |
10 | export const $ = plugins
11 |
12 | export const sassConfig = {
13 | sourceMap: !isProduction,
14 | includePaths: [
15 | paths.modules,
16 | paths.styles,
17 | paths.components
18 | ]
19 | }
20 |
21 | export const faviconsConfig = {
22 | appName: siteConfig.name,
23 | appDescription: siteConfig.description,
24 | developerName: siteConfig.author.name,
25 | developerURL: siteConfig.author.site,
26 | background: '#fff',
27 | path: '/favicons/',
28 | url: `${siteConfig.homepage}/`,
29 | display: 'standalone',
30 | orientation: 'portrait',
31 | start_url: '/?homescreen=1',
32 | version: 1.0,
33 | logging: false,
34 | html: 'favicons.html',
35 | lang: siteConfig.lang,
36 | pipeHTML: true,
37 | replace: true
38 | }
39 |
40 | export const serviceWorker = {
41 | safeToUseOptionalCaches: true,
42 | caches: {
43 | main: ['index.html'],
44 | additional: ['*.js']
45 | },
46 | navigateFallbackURL: '/',
47 | autoUpdate: true,
48 | responseStrategy: 'cache-first',
49 | ServiceWorker: {
50 | events: true
51 | },
52 | AppCache: {
53 | events: true
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/tasks/config/webpack.js:
--------------------------------------------------------------------------------
1 | import webpack from 'webpack'
2 | import MiniCssExtractPlugin from 'mini-css-extract-plugin'
3 | import HtmlWebpackPlugin from 'html-webpack-plugin'
4 | import { CleanWebpackPlugin } from 'clean-webpack-plugin'
5 | import OfflinePlugin from 'offline-plugin'
6 |
7 | import { join, resolve } from 'path'
8 | import { paths } from './paths'
9 | import {
10 | env,
11 | pkg,
12 | isProduction,
13 | siteConfig
14 | } from './base'
15 | import {
16 | serviceWorker,
17 | sassConfig,
18 | faviconsConfig
19 | } from './plugins'
20 |
21 | const outputFile = '[name].bundle.js'
22 | const plugins = []
23 |
24 | plugins.push(new webpack.DefinePlugin({
25 | VERSION: JSON.stringify(pkg.version)
26 | }))
27 |
28 | plugins.push(new webpack.BannerPlugin({
29 | banner: `${pkg.name} - ${pkg.description}
30 | @link ${pkg.homepage}
31 | @version ${pkg.version}
32 | @license ${pkg.license}
33 | @author ${pkg.author.name} <${pkg.author.email}> | ${pkg.author.site}`
34 | }))
35 |
36 | plugins.push(new CleanWebpackPlugin())
37 |
38 | plugins.push(new HtmlWebpackPlugin({
39 | template: resolve(paths.src, 'index.pug'),
40 | hash: true,
41 | cache: true,
42 | templateParameters: {
43 | globals: { ...siteConfig, ...{ favicons: faviconsConfig } }
44 | }
45 | }))
46 |
47 | plugins.push(new MiniCssExtractPlugin({
48 | filename: 'styles/style.[contenthash].css'
49 | }))
50 |
51 | plugins.push(new OfflinePlugin(serviceWorker))
52 |
53 | export const webpackConfig = {
54 | mode: env,
55 | devtool: isProduction ? 'source-map' : '',
56 | entry: join(paths.src, 'index.js'),
57 | output: {
58 | publicPath: '/',
59 | path: paths.dist,
60 | filename: outputFile
61 | },
62 | context: paths.dist,
63 | module: {
64 | rules: [{
65 | test: /\.pug/,
66 | loader: 'pug-loader',
67 | query: {
68 | pretty: !isProduction
69 | }
70 | }, {
71 | test: /\.scss/,
72 | use: [
73 | 'style-loader',
74 | MiniCssExtractPlugin.loader,
75 | {
76 | loader: 'css-loader',
77 | options: {
78 | importLoaders: 1
79 | }
80 | },
81 | 'postcss-loader',
82 | {
83 | loader: 'sass-loader',
84 | options: sassConfig
85 | }
86 | ]
87 | }, {
88 | test: /\.jpe?g$|\.gif$|\.png$|\.svg$/,
89 | use: {
90 | loader: 'file-loader',
91 | options: {
92 | outputPath: 'images',
93 | name: '[name]-[hash].[ext]'
94 | }
95 | }
96 | }, {
97 | test: /\.m?js$/,
98 | exclude: /(node_modules|bower_components)/,
99 | use: {
100 | loader: 'babel-loader',
101 | options: {
102 | presets: ['@babel/preset-env'],
103 | plugins: ['@babel/plugin-proposal-object-rest-spread']
104 | }
105 | }
106 | }]
107 | },
108 | resolve: {
109 | extensions: ['.js'],
110 | modules: [
111 | paths.modules,
112 | paths.scripts
113 | ]
114 | },
115 | plugins
116 | }
117 |
--------------------------------------------------------------------------------
/tasks/favicons.js:
--------------------------------------------------------------------------------
1 | import { src, dest, parallel } from 'gulp'
2 | import { paths, $, faviconsConfig } from './config'
3 |
4 | const _favicons = () =>
5 | src([`${paths.src}/images/icon.png`])
6 | .pipe($.favicons(faviconsConfig))
7 | .pipe(dest(`${paths.dist}${faviconsConfig.path}`))
8 |
9 | const _task = parallel(_favicons)
10 | _task.description = '{{ generate favicons }}'
11 |
12 | export const favicons = _task
13 |
--------------------------------------------------------------------------------
/tasks/index.js:
--------------------------------------------------------------------------------
1 | import { server } from './watch'
2 |
3 | export * from './static'
4 | export * from './favicons'
5 | export * from './build'
6 | export * from './watch'
7 |
8 | export default server
9 |
--------------------------------------------------------------------------------
/tasks/static.js:
--------------------------------------------------------------------------------
1 | import { src, dest, parallel } from 'gulp'
2 | import { paths, $ } from './config'
3 |
4 | const _static = () =>
5 | src([`${paths.static}/*`])
6 | .pipe($.size())
7 | .pipe(dest(paths.dist))
8 |
9 | const _images = () =>
10 | src([`${paths.src}/images/*.{png,jpg,jpeg,gif}`])
11 | .pipe($.size())
12 | .pipe(dest(`${paths.dist}/images`))
13 |
14 | const _task = parallel(_static, _images)
15 | _task.description = '{{ Copy static files and images }}'
16 |
17 | export const copyFiles = _task
18 |
--------------------------------------------------------------------------------
/tasks/watch.js:
--------------------------------------------------------------------------------
1 | import webpack from 'webpack'
2 | import webpackDevMiddleware from 'webpack-dev-middleware'
3 | import webpackHotMiddleware from 'webpack-hot-middleware'
4 | import gulp from 'gulp'
5 | import { paths, $, webpackConfig } from './config'
6 | import { build } from './build'
7 |
8 | const bundler = webpack(webpackConfig)
9 |
10 | const _watchScripts = () =>
11 | gulp.watch(`${paths.src}/**/*.js`, build)
12 |
13 | const _bSync = () => {
14 | $.browserSync.init({
15 | server: {
16 | baseDir: paths.dist
17 | },
18 | middleware: [
19 | webpackDevMiddleware(bundler, { /* options */ }),
20 | webpackHotMiddleware(bundler)
21 | ]
22 | })
23 |
24 | _watchScripts()
25 | gulp.watch(`${paths.dist}/**/*.{html,css,js}`, $.browserSync.reload())
26 | }
27 |
28 | const _build = gulp.series(build)
29 | const _watch = gulp.series(_watchScripts)
30 | const _serve = gulp.series(_build, _bSync)
31 |
32 | _watch.description = '{{ watch for changes to all source }}'
33 | _serve.description = '{{ serve compiled source on local server at port 3000 }}'
34 |
35 | export const watch = _watch
36 | export const server = _serve
37 |
--------------------------------------------------------------------------------