├── .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 |
--------------------------------------------------------------------------------