├── .gitignore ├── static-starter.png ├── mix-manifest.json ├── public ├── fonts │ └── MaisonNeue │ │ ├── maisonneue-book-webfont.woff │ │ └── maisonneue-book-webfont.woff2 ├── index.html └── css │ └── app.css ├── assets ├── scss │ ├── app.scss │ ├── base │ │ ├── _base.scss │ │ └── _helpers.scss │ └── utils │ │ ├── _fonts.scss │ │ └── _variables.scss └── js │ ├── bootstrap.js │ └── app.js ├── webpack.mix.js ├── package.json ├── README.md └── webpack.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .sass-cache 3 | .DS_Store 4 | src 5 | -------------------------------------------------------------------------------- /static-starter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lookstudios/static-starter/HEAD/static-starter.png -------------------------------------------------------------------------------- /mix-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "/public/js/app.js": "/public/js/app.js", 3 | "/public/css/app.css": "/public/css/app.css" 4 | } -------------------------------------------------------------------------------- /public/fonts/MaisonNeue/maisonneue-book-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lookstudios/static-starter/HEAD/public/fonts/MaisonNeue/maisonneue-book-webfont.woff -------------------------------------------------------------------------------- /public/fonts/MaisonNeue/maisonneue-book-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lookstudios/static-starter/HEAD/public/fonts/MaisonNeue/maisonneue-book-webfont.woff2 -------------------------------------------------------------------------------- /assets/scss/app.scss: -------------------------------------------------------------------------------- 1 | // 1. Configuration and helpers 2 | @import 3 | 'utils/variables', 4 | 'utils/fonts'; 5 | 6 | // 2. Base styles 7 | @import 8 | 'base/base', 9 | 'base/helpers'; 10 | -------------------------------------------------------------------------------- /webpack.mix.js: -------------------------------------------------------------------------------- 1 | let mix = require('laravel-mix'); 2 | 3 | mix.options({ 4 | processCssUrls: false 5 | }); 6 | 7 | mix.js('assets/js/app.js', 'public/js/') 8 | .sass('assets/scss/app.scss', 'public/css/'); 9 | -------------------------------------------------------------------------------- /assets/js/bootstrap.js: -------------------------------------------------------------------------------- 1 | window._ = require('lodash'); 2 | window.Vue = require('vue'); 3 | 4 | /** 5 | * We'll load the axios HTTP library which allows us to easily issue requests 6 | * to a back-end. 7 | */ 8 | window.axios = require('axios'); -------------------------------------------------------------------------------- /assets/js/app.js: -------------------------------------------------------------------------------- 1 | /** 2 | * First we will load all of this project's JavaScript dependencies which 3 | * includes Vue and other libraries. It is a great starting point when 4 | * building robust, powerful web applications using Vue. 5 | */ 6 | require('./bootstrap'); -------------------------------------------------------------------------------- /assets/scss/base/_base.scss: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | html { 8 | font-family: $text-font-stack; 9 | color: $text-black; 10 | background-color: $bg-white; 11 | -webkit-font-smoothing: antialiased; 12 | } 13 | -------------------------------------------------------------------------------- /assets/scss/utils/_fonts.scss: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'maison_neue'; 3 | src: url('../fonts/MaisonNeue/maisonneue-book-webfont.woff2') format('woff2'), 4 | url('../fonts/MaisonNeue/maisonneue-book-webfont.woff') format('woff'); 5 | font-weight: 400; 6 | font-style: normal; 7 | } -------------------------------------------------------------------------------- /assets/scss/base/_helpers.scss: -------------------------------------------------------------------------------- 1 | // Grid 2 | .wrap { 3 | margin: 0 auto; 4 | padding: 0 auto; 5 | max-width: $wrap; 6 | width: 100%; 7 | } 8 | 9 | //Flex 10 | .level { 11 | display: flex; 12 | 13 | .flex { 14 | flex: 1; 15 | } 16 | } 17 | 18 | // Colors 19 | .t-black { color: $text-black } 20 | .bg-white { background-color: $bg-white } 21 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Static Starter 6 | 7 | 8 | 9 | 10 |

Static Starter

11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /assets/scss/utils/_variables.scss: -------------------------------------------------------------------------------- 1 | // Fonts 2 | $text-font-stack: 'maison_neue', 'Arial', sans-serif !default; 3 | $text-weight-light: 300 !default; 4 | $text-weight-regular: 400 !default; 5 | $text-weight-medium: 500 !default; 6 | $text-weight-bold: 700 !default; 7 | 8 | 9 | // Colors 10 | $text-black: #222222 !default; 11 | $bg-white: #FFFFFF !default; 12 | 13 | 14 | // Wraps 15 | $wrap: 960px !default; 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "static-starter", 3 | "version": "1.0.0", 4 | "description": "🏃🏻", 5 | "main": "index.html", 6 | "scripts": { 7 | "dev": "cross-env NODE_ENV=development webpack --progress --hide-modules", 8 | "watch": "cross-env NODE_ENV=development webpack --watch --progress --hide-modules", 9 | "hot": "cross-env NODE_ENV=development webpack-dev-server --inline --hot", 10 | "production": "cross-env NODE_ENV=production webpack --progress --hide-modules" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "http://github.com/lookstudios/static-starter" 15 | }, 16 | "devDependencies": { 17 | "browser-sync": "^2.0.0", 18 | "cross-env": "^4.0.0", 19 | "laravel-mix": "^0.11.3", 20 | "webpack": "^2.4.1" 21 | }, 22 | "dependencies": { 23 | "axios": "^0.16.1", 24 | "lodash": "^4.17.4", 25 | "vue": "^2.2.6" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /public/css/app.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'maison_neue'; 3 | src: url("../fonts/MaisonNeue/maisonneue-book-webfont.woff2") format("woff2"), url("../fonts/MaisonNeue/maisonneue-book-webfont.woff") format("woff"); 4 | font-weight: 400; 5 | font-style: normal; 6 | } 7 | 8 | * { 9 | margin: 0; 10 | padding: 0; 11 | box-sizing: border-box; 12 | } 13 | 14 | html { 15 | font-family: "maison_neue", "Arial", sans-serif; 16 | color: #222222; 17 | background-color: #FFFFFF; 18 | -webkit-font-smoothing: antialiased; 19 | } 20 | 21 | .wrap { 22 | margin: 0 auto; 23 | padding: 0 auto; 24 | max-width: 960px; 25 | width: 100%; 26 | } 27 | 28 | .level { 29 | display: -webkit-box; 30 | display: -ms-flexbox; 31 | display: flex; 32 | } 33 | 34 | .level .flex { 35 | -webkit-box-flex: 1; 36 | -ms-flex: 1; 37 | flex: 1; 38 | } 39 | 40 | .t-black { 41 | color: #222222; 42 | } 43 | 44 | .bg-white { 45 | background-color: #FFFFFF; 46 | } 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Static Starter 2 | A static starter for small sites. We're compiling with Laravel.Mix which has a lot of handy helpers over the top of webpack. 3 | 4 | ## Installation 5 | - Clone `git clone https://github.com/lookstudios/static-starter.git` 6 | - [Download latest version](https://github.com/lookstudios/static-starter/archive/master.zip) 7 | 8 | ### Installing Assets 9 | - `cd static-starter` 10 | - `npm install` or `yarn` 11 | 12 | ### Compiling assets 13 | - `npm run dev` - Compiles development mode 14 | - `npm run production` - Compiles assets down for production usage 15 | - `npm run watch` - Runs a watcher and auto compiles when assets are updated 16 | 17 | ## Features 18 | - Auto compress images 19 | - Auto compile JS & Sass 20 | - Auto prefixes 21 | - Supports hot reloading 22 | - Supports browser sync 23 | - ES6 support 24 | - Vue files support 25 | - Compresses images 26 | - Multiple enviroments for different compiling methods 27 | 28 | ## Support 29 | - [bobby@lookstudios.co](mailto:bobby@lookstudios.co) 30 | - [joe@lookstudios.co](mailto:joe@lookstudios.co) 31 | - [@lookstudiosco](http://twitter.com/lookstudiosco) 32 | 33 | ## License 34 | MIT 35 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | let path = require('path'); 2 | let glob = require('glob'); 3 | let webpack = require('webpack'); 4 | let Mix = require('laravel-mix').config; 5 | let webpackPlugins = require('laravel-mix').plugins; 6 | let dotenv = require('dotenv') 7 | 8 | /* 9 | |-------------------------------------------------------------------------- 10 | | Load Environment Variables 11 | |-------------------------------------------------------------------------- 12 | | 13 | | Load environment variables from .env file. dotenv will never modify 14 | | any environment variables that have already been set. 15 | | 16 | */ 17 | 18 | dotenv.config({ 19 | path: Mix.Paths.root('.env') 20 | }); 21 | 22 | 23 | 24 | /* 25 | |-------------------------------------------------------------------------- 26 | | Mix Initialization 27 | |-------------------------------------------------------------------------- 28 | | 29 | | As our first step, we'll require the project's Laravel Mix file 30 | | and record the user's requested compilation and build steps. 31 | | Once those steps have been recorded, we may get to work. 32 | | 33 | */ 34 | 35 | Mix.initialize(); 36 | 37 | 38 | 39 | /* 40 | |-------------------------------------------------------------------------- 41 | | Webpack Context 42 | |-------------------------------------------------------------------------- 43 | | 44 | | This prop will determine the appropriate context, when running Webpack. 45 | | Since you have the option of publishing this webpack.config.js file 46 | | to your project root, we will dynamically set the path for you. 47 | | 48 | */ 49 | 50 | module.exports.context = Mix.Paths.root(); 51 | 52 | 53 | 54 | /* 55 | |-------------------------------------------------------------------------- 56 | | Webpack Entry 57 | |-------------------------------------------------------------------------- 58 | | 59 | | We'll first specify the entry point for Webpack. By default, we'll 60 | | assume a single bundled file, but you may call Mix.extract() 61 | | to make a separate bundle specifically for vendor libraries. 62 | | 63 | */ 64 | 65 | module.exports.entry = Mix.entry().get(); 66 | 67 | 68 | 69 | /* 70 | |-------------------------------------------------------------------------- 71 | | Webpack Output 72 | |-------------------------------------------------------------------------- 73 | | 74 | | Webpack naturally requires us to specify our desired output path and 75 | | file name. We'll simply echo what you passed to with Mix.js(). 76 | | Note that, for Mix.version(), we'll properly hash the file. 77 | | 78 | */ 79 | 80 | module.exports.output = Mix.output(); 81 | 82 | 83 | 84 | /* 85 | |-------------------------------------------------------------------------- 86 | | Rules 87 | |-------------------------------------------------------------------------- 88 | | 89 | | Webpack rules allow us to register any number of loaders and options. 90 | | Out of the box, we'll provide a handful to get you up and running 91 | | as quickly as possible, though feel free to add to this list. 92 | | 93 | */ 94 | 95 | let plugins = []; 96 | 97 | if (Mix.options.extractVueStyles) { 98 | var vueExtractTextPlugin = Mix.vueExtractTextPlugin(); 99 | 100 | plugins.push(vueExtractTextPlugin); 101 | } 102 | 103 | let rules = [ 104 | { 105 | test: /\.vue$/, 106 | loader: 'vue-loader', 107 | options: { 108 | loaders: Mix.options.extractVueStyles ? { 109 | js: 'babel-loader' + Mix.babelConfig(), 110 | scss: vueExtractTextPlugin.extract({ 111 | use: 'css-loader!sass-loader', 112 | fallback: 'vue-style-loader' 113 | }), 114 | sass: vueExtractTextPlugin.extract({ 115 | use: 'css-loader!sass-loader?indentedSyntax', 116 | fallback: 'vue-style-loader' 117 | }), 118 | less: vueExtractTextPlugin.extract({ 119 | use: 'css-loader!less-loader', 120 | fallback: 'vue-style-loader' 121 | }), 122 | stylus: vueExtractTextPlugin.extract({ 123 | use: 'css-loader!stylus-loader?paths[]=node_modules', 124 | fallback: 'vue-style-loader' 125 | }), 126 | css: vueExtractTextPlugin.extract({ 127 | use: 'css-loader', 128 | fallback: 'vue-style-loader' 129 | }) 130 | }: { 131 | js: 'babel-loader' + Mix.babelConfig(), 132 | scss: 'vue-style-loader!css-loader!sass-loader', 133 | sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax', 134 | less: 'vue-style-loader!css-loader!less-loader', 135 | stylus: 'vue-style-loader!css-loader!stylus-loader?paths[]=node_modules' 136 | }, 137 | 138 | postcss: Mix.options.postCss, 139 | 140 | preLoaders: Mix.options.vue.preLoaders, 141 | 142 | postLoaders: Mix.options.vue.postLoaders 143 | } 144 | }, 145 | 146 | { 147 | test: /\.jsx?$/, 148 | exclude: /(node_modules|bower_components)/, 149 | loader: 'babel-loader' + Mix.babelConfig() 150 | }, 151 | 152 | { 153 | test: /\.css$/, 154 | loaders: ['style-loader', 'css-loader'] 155 | }, 156 | 157 | { 158 | test: /\.html$/, 159 | loaders: ['html-loader'] 160 | }, 161 | 162 | { 163 | test: /\.(png|jpe?g|gif)$/, 164 | loaders: [ 165 | { 166 | loader: 'file-loader', 167 | options: { 168 | name: path => { 169 | if (! /node_modules|bower_components/.test(path)) { 170 | return 'images/[name].[ext]?[hash]'; 171 | } 172 | 173 | return 'images/vendor/' + path 174 | .replace(/\\/g, '/') 175 | .replace( 176 | /((.*(node_modules|bower_components))|images|image|img|assets)\//g, '' 177 | ) + '?[hash]'; 178 | }, 179 | publicPath: Mix.options.resourceRoot 180 | } 181 | }, 182 | 'img-loader' 183 | ] 184 | }, 185 | 186 | { 187 | test: /\.(woff2?|ttf|eot|svg|otf)$/, 188 | loader: 'file-loader', 189 | options: { 190 | name: path => { 191 | if (! /node_modules|bower_components/.test(path)) { 192 | return 'fonts/[name].[ext]?[hash]'; 193 | } 194 | 195 | return 'fonts/vendor/' + path 196 | .replace(/\\/g, '/') 197 | .replace( 198 | /((.*(node_modules|bower_components))|fonts|font|assets)\//g, '' 199 | ) + '?[hash]'; 200 | }, 201 | publicPath: Mix.options.resourceRoot 202 | } 203 | }, 204 | 205 | { 206 | test: /\.(cur|ani)$/, 207 | loader: 'file-loader', 208 | options: { 209 | name: '[name].[ext]?[hash]', 210 | publicPath: Mix.options.resourceRoot 211 | } 212 | } 213 | ]; 214 | 215 | let sassRule = { 216 | test: /\.s[ac]ss$/, 217 | loaders: ['style-loader', 'css-loader', 'sass-loader'] 218 | }; 219 | 220 | if (Mix.preprocessors) { 221 | sassRule.exclude = Mix.preprocessors.map(preprocessor => preprocessor.test()); 222 | } 223 | 224 | rules.push(sassRule); 225 | 226 | if (Mix.preprocessors) { 227 | Mix.preprocessors.forEach(preprocessor => { 228 | rules.push(preprocessor.rules()); 229 | 230 | plugins.push(preprocessor.extractPlugin); 231 | }); 232 | } 233 | 234 | module.exports.module = { rules }; 235 | 236 | 237 | 238 | /* 239 | |-------------------------------------------------------------------------- 240 | | Resolve 241 | |-------------------------------------------------------------------------- 242 | | 243 | | Here, we may set any options/aliases that affect Webpack's resolving 244 | | of modules. To begin, we will provide the necessary Vue alias to 245 | | load the Vue common library. You may delete this, if needed. 246 | | 247 | */ 248 | 249 | module.exports.resolve = { 250 | extensions: ['*', '.js', '.jsx', '.vue'], 251 | 252 | alias: { 253 | 'vue$': 'vue/dist/vue.common.js' 254 | } 255 | }; 256 | 257 | 258 | 259 | /* 260 | |-------------------------------------------------------------------------- 261 | | Stats 262 | |-------------------------------------------------------------------------- 263 | | 264 | | By default, Webpack spits a lot of information out to the terminal, 265 | | each you time you compile. Let's keep things a bit more minimal 266 | | and hide a few of those bits and pieces. Adjust as you wish. 267 | | 268 | */ 269 | 270 | module.exports.stats = { 271 | hash: false, 272 | version: false, 273 | timings: false, 274 | children: false, 275 | errors: false 276 | }; 277 | 278 | process.noDeprecation = true; 279 | 280 | module.exports.performance = { hints: false }; 281 | 282 | 283 | 284 | /* 285 | |-------------------------------------------------------------------------- 286 | | Devtool 287 | |-------------------------------------------------------------------------- 288 | | 289 | | Sourcemaps allow us to access our original source code within the 290 | | browser, even if we're serving a bundled script or stylesheet. 291 | | You may activate sourcemaps, by adding Mix.sourceMaps(). 292 | | 293 | */ 294 | 295 | module.exports.devtool = Mix.options.sourcemaps; 296 | 297 | 298 | 299 | /* 300 | |-------------------------------------------------------------------------- 301 | | Webpack Dev Server Configuration 302 | |-------------------------------------------------------------------------- 303 | | 304 | | If you want to use that flashy hot module replacement feature, then 305 | | we've got you covered. Here, we'll set some basic initial config 306 | | for the Node server. You very likely won't want to edit this. 307 | | 308 | */ 309 | module.exports.devServer = { 310 | historyApiFallback: true, 311 | noInfo: true, 312 | compress: true, 313 | quiet: true 314 | }; 315 | 316 | 317 | 318 | /* 319 | |-------------------------------------------------------------------------- 320 | | Plugins 321 | |-------------------------------------------------------------------------- 322 | | 323 | | Lastly, we'll register a number of plugins to extend and configure 324 | | Webpack. To get you started, we've included a handful of useful 325 | | extensions, for versioning, OS notifications, and much more. 326 | | 327 | */ 328 | 329 | plugins.push( 330 | new webpack.ProvidePlugin(Mix.autoload || {}), 331 | 332 | new webpackPlugins.FriendlyErrorsWebpackPlugin({ clearConsole: Mix.options.clearConsole }), 333 | 334 | new webpackPlugins.StatsWriterPlugin({ 335 | filename: 'mix-manifest.json', 336 | transform: Mix.manifest.transform.bind(Mix.manifest), 337 | }), 338 | 339 | new webpack.LoaderOptionsPlugin({ 340 | minimize: Mix.inProduction, 341 | options: { 342 | postcss: Mix.options.postCss, 343 | context: __dirname, 344 | output: { path: './' } 345 | } 346 | }) 347 | ); 348 | 349 | if (Mix.browserSync) { 350 | plugins.push( 351 | new webpackPlugins.BrowserSyncPlugin( 352 | Object.assign({ 353 | host: 'localhost', 354 | port: 3000, 355 | proxy: 'app.dev', 356 | files: [ 357 | 'app/**/*.php', 358 | 'resources/views/**/*.php', 359 | 'public/js/**/*.js', 360 | 'public/css/**/*.css' 361 | ] 362 | }, Mix.browserSync), 363 | { 364 | reload: false 365 | } 366 | ) 367 | ); 368 | } 369 | 370 | if (Mix.options.notifications) { 371 | plugins.push( 372 | new webpackPlugins.WebpackNotifierPlugin({ 373 | title: 'Static Starter', 374 | alwaysNotify: true, 375 | contentImage: Mix.Paths.root('static-starter.png') 376 | }) 377 | ); 378 | } 379 | 380 | if (Mix.copy.length) { 381 | new webpackPlugins.CopyWebpackPlugin(Mix.copy); 382 | } 383 | 384 | if (Mix.entry().hasExtractions()) { 385 | plugins.push( 386 | new webpack.optimize.CommonsChunkPlugin({ 387 | names: Mix.entry().getExtractions(), 388 | minChunks: Infinity 389 | }) 390 | ); 391 | } 392 | 393 | if (Mix.options.versioning) { 394 | plugins.push( 395 | new webpack[Mix.inProduction ? 'HashedModuleIdsPlugin': 'NamedModulesPlugin'](), 396 | new webpackPlugins.WebpackChunkHashPlugin() 397 | ); 398 | } 399 | 400 | if (Mix.options.purifyCss) { 401 | let PurifyCSSPlugin = require('purifycss-webpack'); 402 | 403 | // By default, we'll scan all Blade and Vue files in our project. 404 | let paths = glob.sync(Mix.Paths.root('resources/views/**/*.blade.php')).concat( 405 | Mix.entry().scripts.reduce((carry, js) => { 406 | return carry.concat(glob.sync(js.base + '/**/*.vue')); 407 | }, []) 408 | ); 409 | 410 | plugins.push(new PurifyCSSPlugin( 411 | Object.assign({ paths }, Mix.options.purifyCss, { minimize: Mix.inProduction }) 412 | )); 413 | } 414 | 415 | if (Mix.inProduction && Mix.options.uglify) { 416 | plugins.push( 417 | new webpack.optimize.UglifyJsPlugin(Mix.options.uglify) 418 | ); 419 | } 420 | 421 | plugins.push( 422 | new webpack.DefinePlugin( 423 | Mix.definitions({ 424 | NODE_ENV: Mix.inProduction 425 | ? 'production' 426 | : ( process.env.NODE_ENV || 'development' ) 427 | }) 428 | ), 429 | 430 | new webpackPlugins.WebpackOnBuildPlugin( 431 | stats => global.events.fire('build', stats) 432 | ) 433 | ); 434 | 435 | if (! Mix.entry().hasScripts()) { 436 | plugins.push(new webpackPlugins.MockEntryPlugin(Mix.output().path)); 437 | } 438 | 439 | module.exports.plugins = plugins; 440 | 441 | 442 | 443 | /* 444 | |-------------------------------------------------------------------------- 445 | | Mix Finalizing 446 | |-------------------------------------------------------------------------- 447 | | 448 | | Now that we've declared the entirety of our Webpack configuration, the 449 | | final step is to scan for any custom configuration in the Mix file. 450 | | If mix.webpackConfig() is called, we'll merge it in, and build! 451 | | 452 | */ 453 | 454 | if (Mix.webpackConfig) { 455 | module.exports = require('webpack-merge').smart( 456 | module.exports, Mix.webpackConfig 457 | ); 458 | } 459 | --------------------------------------------------------------------------------