├── CHANGELOG.md ├── assets ├── fonts │ └── .gitkeep ├── icons │ └── .gitkeep ├── images │ └── .gitkeep ├── scss │ └── common.scss └── scripts │ └── common.js ├── docs ├── CHANGELOG.md └── 01-index.md ├── public └── assets │ └── images │ └── .gitkeep ├── .gitignore ├── .browserslistrc ├── babel.config.js ├── components ├── example │ ├── example.config.yml │ └── example.nunj ├── _icon.nunj └── _preview.nunj ├── server.js ├── .editorconfig ├── .release-it.json ├── LICENSE ├── fractal.js ├── package.json ├── webpack.config.js └── README.md /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/fonts/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/icons/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ../CHANGELOG.md -------------------------------------------------------------------------------- /public/assets/images/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | /dist 3 | -------------------------------------------------------------------------------- /.browserslistrc: -------------------------------------------------------------------------------- 1 | last 2 versions 2 | not dead 3 | IE 11 4 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ["@babel/env"], 3 | }; 4 | -------------------------------------------------------------------------------- /components/example/example.config.yml: -------------------------------------------------------------------------------- 1 | title: Example component 2 | context: 3 | text: This is an example component! 4 | -------------------------------------------------------------------------------- /docs/01-index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Overview 3 | --- 4 | 5 | This is your index page. You can edit its contents at `docs/01-index.md` 6 | -------------------------------------------------------------------------------- /components/_icon.nunj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/scss/common.scss: -------------------------------------------------------------------------------- 1 | // This is the main stylesheet file 2 | 3 | body { 4 | color: blue; 5 | 6 | // Include an icon from your sprite example: 7 | // background-image: url('../icons/home.svg'); 8 | } 9 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | const fractal = require('./fractal.js'); 2 | const server = fractal.web.server(); 3 | 4 | server.start().then(function(){ 5 | console.log(`Fractal server is now running.`); 6 | }); 7 | 8 | server.stop(); -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | 6 | indent_style = space 7 | indent_size = 2 8 | 9 | end_of_line = lf 10 | trim_trailing_whitespace = true 11 | insert_final_newline = true 12 | 13 | [*.md] 14 | indent_size = 4 15 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /components/example/example.nunj: -------------------------------------------------------------------------------- 1 |

{{ text }}

2 | 3 | {# Use the icon partial for easy inclusion #} 4 | {# {% render '@icon', { id: 'home', class: 'icon--small' } %} #} 5 | {# Where "home" is the icon file name without the extension #} 6 | {# Don’t forget to import your icons first in assets/scripts/common.js #} 7 | -------------------------------------------------------------------------------- /.release-it.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "afterRelease": "npm run deploy", 4 | "afterBump": "npm run build" 5 | }, 6 | "npm": { 7 | "publish": false 8 | }, 9 | "plugins": { 10 | "@release-it/conventional-changelog": { 11 | "preset": "angular", 12 | "infile": "CHANGELOG.md" 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /assets/scripts/common.js: -------------------------------------------------------------------------------- 1 | // This file is the webpack entry point 2 | 3 | // Import the main Sass file 4 | import 'scss/common.scss'; 5 | 6 | // Here you can import your components, icons, etc. 7 | // For example: 8 | // 9 | // import modal from 'components/Modal'; 10 | // import 'icons/home.svg'; 11 | // 12 | // Webpack will automatically look for files relative to `assets/scripts/` and `assets/`. 13 | 14 | console.log('Common bundle loaded.'); 15 | -------------------------------------------------------------------------------- /components/_preview.nunj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Preview Layout 9 | 10 | 11 | 12 | 13 | {{ yield | safe }} 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Liip AG, liip.ch 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 | -------------------------------------------------------------------------------- /fractal.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | const fractal = module.exports = require('@frctl/fractal').create(); 4 | const pkg = require(path.join(__dirname, 'package.json')); 5 | 6 | 7 | /*-------------------------------------------------------*\ 8 | Feel free to adapt Fractal config below to your needs 9 | \*-------------------------------------------------------*/ 10 | 11 | /** 12 | * Metadata 13 | */ 14 | fractal.set('project.title', 'Styleguide Starterkit'); 15 | // Provide the package.json "version" to the templates 16 | fractal.set('project.version', pkg.version); 17 | 18 | /** 19 | * Files location 20 | */ 21 | fractal.components.set('path', path.join(__dirname, 'components')); 22 | fractal.docs.set('path', path.join(__dirname, 'docs')); 23 | fractal.web.set('static.path', path.join(__dirname, 'public')); 24 | 25 | /** 26 | * Build options 27 | */ 28 | // If you change the build destination, you should adapt webpack.common.js "output.path" too. 29 | fractal.web.set('builder.dest', 'dist'); 30 | 31 | /** 32 | * Templating 33 | */ 34 | // Use Nunjucks as the template engine 35 | fractal.components.engine('@frctl/nunjucks'); 36 | fractal.docs.engine('@frctl/nunjucks'); 37 | // Look for templates with a ".nunj" extension 38 | fractal.components.set('ext', '.nunj'); 39 | 40 | 41 | /*----------------------------------------*\ 42 | Change the following at your own risk 43 | \*----------------------------------------*/ 44 | 45 | /** 46 | * Server configuration 47 | */ 48 | fractal.web.set('server.port', 4000); 49 | fractal.web.set('server.sync', true); 50 | 51 | /** 52 | * Prevent Bluebird warnings like "a promise was created in a handler but was not returned from it" 53 | * caused by Nunjucks from polluting the console 54 | */ 55 | const bluebird = require('bluebird'); 56 | bluebird.config({ 57 | warnings: false 58 | }); 59 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "styleguide-starterkit", 3 | "version": "0.5.0", 4 | "description": "A starterkit to create styleguides with Fractal and Webpack.", 5 | "keywords": [ 6 | "styleguide", 7 | "toolkit", 8 | "boilerplate", 9 | "starterkit", 10 | "fractal" 11 | ], 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/liip/styleguide-starterkit.git" 15 | }, 16 | "license": "MIT", 17 | "scripts": { 18 | "start": "NODE_ENV=development concurrently 'node ./server.js' 'webpack-dev-server --hot'", 19 | "build": "NODE_ENV=production concurrently 'npm run build:fractal' 'npm run build:webpack'", 20 | "build:webpack": "NODE_ENV=production webpack", 21 | "build:fractal": "NODE_ENV=production fractal build", 22 | "release": "release-it", 23 | "deploy": "echo \"No deploy script specified, skipping…\" && exit 0" 24 | }, 25 | "devDependencies": { 26 | "@babel/core": "^7.10.2", 27 | "@babel/preset-env": "^7.10.2", 28 | "@frctl/fractal": "^1.3.0", 29 | "@frctl/nunjucks": "^2.0.2", 30 | "@release-it/conventional-changelog": "^1.1.4", 31 | "autoprefixer": "^9.8.0", 32 | "babel-loader": "^8.1.0", 33 | "concurrently": "^5.2.0", 34 | "css-loader": "^3.5.3", 35 | "cssnano": "^4.1.10", 36 | "file-loader": "^6.0.0", 37 | "marked": "^1.1.0", 38 | "mini-css-extract-plugin": "^0.9.0", 39 | "node-sass": "^4.14.1", 40 | "postcss": "^7.0.32", 41 | "postcss-cli": "^7.1.1", 42 | "postcss-loader": "^3.0.0", 43 | "release-it": "^13.6.2", 44 | "sass-loader": "^8.0.2", 45 | "svg-sprite-loader": "^5.0.0", 46 | "svgo": "^1.3.2", 47 | "svgo-loader": "^2.2.1", 48 | "webpack": "^4.43.0", 49 | "webpack-cli": "^3.3.11", 50 | "webpack-dev-server": "^3.11.0" 51 | }, 52 | "engines": { 53 | "node": ">=6 <=10" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | const MiniCssExtractPlugin = require('mini-css-extract-plugin'); 4 | const SpriteLoaderPlugin = require('svg-sprite-loader/plugin'); 5 | 6 | module.exports = { 7 | mode: process.env.NODE_ENV, 8 | resolve: { 9 | modules: [ 10 | path.resolve(__dirname, 'assets/scripts'), 11 | path.resolve(__dirname, 'assets'), 12 | 'node_modules' 13 | ], 14 | extensions: ['.js'] 15 | }, 16 | entry: { 17 | common: path.resolve(__dirname, 'assets/scripts/common.js'), 18 | }, 19 | output: { 20 | path: path.resolve(__dirname, 'dist'), 21 | publicPath: '/', 22 | filename: '[name].js' 23 | }, 24 | module: { 25 | rules: [ 26 | { 27 | test: /\.js$/, 28 | exclude: /node_modules/, 29 | loader: 'babel-loader', 30 | }, 31 | { 32 | test: /\.scss$/, 33 | use: [ 34 | { 35 | loader: MiniCssExtractPlugin.loader, 36 | options: { 37 | hmr: process.env.NODE_ENV === 'development', 38 | } 39 | }, 40 | 'css-loader', 41 | { 42 | loader: 'postcss-loader', 43 | options: { 44 | plugins: [ 45 | require('autoprefixer')(), 46 | require('cssnano')(), 47 | ], 48 | }, 49 | }, 50 | { 51 | loader: 'sass-loader', 52 | options: { 53 | sassOptions: { 54 | includePaths: ['node_modules'], 55 | } 56 | }, 57 | }, 58 | ], 59 | }, 60 | { 61 | test: /\.(svg|png|jpe?g|gif|woff|woff2|eot|ttf|otf)$/, 62 | exclude: path.resolve('./assets/icons'), 63 | use: [ 64 | { 65 | loader: 'file-loader', 66 | options: { 67 | name: '[name].[ext]', 68 | outputPath: 'assets/', 69 | } 70 | } 71 | ] 72 | }, 73 | { 74 | test: /\.svg$/, 75 | include: path.resolve('./assets/icons'), 76 | use: [ 77 | { 78 | loader: 'svg-sprite-loader', 79 | options: { 80 | extract: true, 81 | spriteFilename: 'assets/icons.svg', 82 | esModule: false, 83 | } 84 | }, 85 | 'svgo-loader' 86 | ], 87 | } 88 | ] 89 | }, 90 | plugins: [ 91 | new MiniCssExtractPlugin(), 92 | new SpriteLoaderPlugin(), 93 | ], 94 | devServer: { 95 | historyApiFallback: true, 96 | compress: true, 97 | proxy: { 98 | '**': 'http://localhost:4000' 99 | }, 100 | port: 3000, 101 | stats: { 102 | colors: true 103 | }, 104 | overlay: true, 105 | }, 106 | optimization: { 107 | splitChunks: { 108 | cacheGroups: { 109 | styles: { 110 | name: 'styles', 111 | test: /\.css$/, 112 | chunks: 'all', 113 | enforce: true, 114 | }, 115 | }, 116 | }, 117 | }, 118 | }; 119 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Styleguide starterkit 2 | 3 | A starterkit to create web styleguides with [Fractal](http://fractal.build/) and [Webpack](https://webpack.js.org/). 4 | 5 | - Fractal pre-configured with [Nunjucks](https://mozilla.github.io/nunjucks/) 6 | - JavaScript bundling with Webpack and [Babel](http://babeljs.io/) 7 | - Sass compilation, including [Autoprefixer](https://github.com/postcss/autoprefixer) 8 | - [SVG icons sprite](https://css-tricks.com/svg-symbol-good-choice-icons/) generation 9 | - Live reload (with hot module replacement) for comfortable development 10 | - Automated release management with [release-it](https://github.com/webpro/release-it) 11 | 12 | 13 | ## Installation 14 | 15 | Prerequisites: [Node.js](https://nodejs.org/en/) >= 10, <= 12 16 | 17 | Inside the directory of your choice, install a copy of the starterkit with: 18 | 19 | ```bash 20 | curl -L https://github.com/liip/styleguide-starterkit/archive/master.tar.gz | tar zx --strip 1 21 | ``` 22 | 23 | Then install the npm dependencies with: 24 | 25 | ```bash 26 | npm install 27 | ``` 28 | 29 | 30 | ## Getting started 31 | 32 | To start the development server, run: 33 | 34 | ```bash 35 | npm start 36 | ``` 37 | 38 | You can now access your styleguide at [localhost:3000](http://localhost:3000). 39 | 40 | You’re all set, start to: 41 | 42 | - Create components as `.nunj` (Nunjucks) files inside the `components` directory 43 | - Write some style inside `assets/scss/common.scss` 44 | - Write JavaScript inside `assets/scripts/common.js` 45 | - Put some `*.svg` icons in the `assets/icons` directory 46 | - Write documentation as `.md` (Markdown) files inside the `docs` directory. 47 | 48 | 49 | ## Build 50 | 51 | You can build a static version of the styleguide to deploy it wherever you like by running: 52 | 53 | ``` 54 | npm run build 55 | ``` 56 | 57 | The generated files go to the `dist` directory. 58 | 59 | 60 | ## Release 61 | 62 | The starterkit comes with a preconfigured release management tool. It will automatically update the `CHANGELOG.md` file at the root of the project based on the commit messages as long as they follow the [Angular commit guidelines](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#-git-commit-guidelines). It will also bump the version number in the `package.json`, run the build command above, commit, tag and push the changes. This process is interactive and you’ll be able to skip steps manually if you like. 63 | 64 | To release a new version run: 65 | 66 | ```bash 67 | npm run release [patch|minor|major|version_number] 68 | ``` 69 | 70 | By default the version bump is automatically determined based on the commits messages. 71 | 72 | Read more in the [release-it documentation](https://github.com/webpro/release-it). 73 | 74 | ## Deploy 75 | 76 | To deploy a build of the styleguide, simply replace the blank command in the `package.json`, under `scripts -> deploy`. This will be automatically invoked at the end of the release process described above. 77 | 78 | An example of a simple deploy command using `rsync`: 79 | 80 | ```json 81 | "deploy": "rsync -avz --delete --exclude='.*' dist/ user@server.com:/var/www/html/my-styleguide" 82 | ``` 83 | 84 | ⚠️ Notice the `--delete` flag which means all files not present locally will be deleted on the remote server. Be careful, this can leads to data loss! 85 | 86 | You can also deploy manually at any time by running: 87 | 88 | ```bash 89 | npm run deploy 90 | ``` 91 | 92 | 93 | ## Misc 94 | 95 | ### Browsers support 96 | 97 | The browsers support is defined in `.browserslistrc`. It’s used both by [Autoprefixer](https://github.com/postcss/autoprefixer) for the CSS and by [@babel/preset-env](https://babeljs.io/docs/en/babel-preset-env) for the JavaScript. 98 | 99 | Check [browserslist’s documentation](https://github.com/ai/browserslist) to change the browser support. 100 | 101 | ### Icons 102 | 103 | Icons placed inside `assets/icons` are combined into a sprite called `icons.svg` when referenced. To load them, either reference them in your JavaScript: 104 | 105 | ```js 106 | import 'icons/foo.svg'; 107 | ``` 108 | 109 | Or in your stylesheet: 110 | 111 | ```scss 112 | background-image: url('../icons/foo.svg'); 113 | ``` 114 | 115 | Webpack will automatically rewrite the links to the sprite with the correct identifier. See [svg-sprite-loader](https://github.com/kisenka/svg-sprite-loader) documentation for more information. 116 | 117 | You can then easily use an icon in a template with the icon snippet: 118 | 119 | ```nunj 120 | {% render '@icon', { id: 'foo', class: 'bar' } %} 121 | ``` 122 | 123 | **Warning:** This method of including remote SVG file is not supported by Internet Explorer 11 and below. You may want to polyfill it with [svgxuse](https://github.com/Keyamoon/svgxuse). 124 | --------------------------------------------------------------------------------