├── src ├── images │ └── .gitkeep ├── scss │ ├── blocks │ │ ├── .gitkeep │ │ ├── _swatch.scss │ │ ├── _code-sample.scss │ │ └── _side-nav.scss │ ├── utilities │ │ ├── _auto-grid.scss │ │ ├── _flow.scss │ │ ├── _visually-hidden.scss │ │ ├── _wrapper.scss │ │ └── _sidebar.scss │ ├── _reset.scss │ ├── critical.scss │ └── _config.scss ├── _includes │ ├── partials │ │ ├── site-head.njk │ │ ├── pagination.njk │ │ └── meta-info.njk │ ├── layouts │ │ ├── page.njk │ │ ├── home.njk │ │ └── base.njk │ └── prototype.js ├── patterns │ ├── patterns.json │ ├── button │ │ ├── button.njk │ │ ├── button.json │ │ ├── variants │ │ │ ├── button-secondary.njk │ │ │ └── button-secondary.json │ │ └── docs.md │ └── toggle-switch │ │ ├── toggle-switch.json │ │ ├── toggle-switch.njk │ │ └── docs.md ├── _data │ ├── site.json │ ├── navigation.json │ ├── global.js │ ├── helpers.js │ ├── patterns.js │ └── tokens.json ├── index.md ├── typography.njk ├── filters │ └── markdown-filter.js ├── about.md ├── colors.njk ├── pattern.njk └── preview.njk ├── .eleventyignore ├── netlify.toml ├── .prettierrc ├── .gitignore ├── gulp-tasks ├── fonts.js ├── images.js └── sass.js ├── readme.md ├── .eleventy.js ├── package.json └── gulpfile.js /src/images/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/scss/blocks/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.eleventyignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /src/_includes/partials/site-head.njk: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/patterns/patterns.json: -------------------------------------------------------------------------------- 1 | { 2 | "permalink": false 3 | } 4 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | command = "npm run production" 3 | publish = "dist" -------------------------------------------------------------------------------- /src/patterns/button/button.njk: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/patterns/button/button.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Button", 3 | "text": "A button" 4 | } 5 | -------------------------------------------------------------------------------- /src/patterns/button/variants/button-secondary.njk: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/patterns/button/variants/button-secondary.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Button Secondary", 3 | "text": "A secondary button" 4 | } 5 | -------------------------------------------------------------------------------- /src/_data/site.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "11ty Pattern Library", 3 | "url": "https://example.com", 4 | "authorName": "Base Author", 5 | "authorEmail": "hi@example.com" 6 | } 7 | -------------------------------------------------------------------------------- /src/patterns/toggle-switch/toggle-switch.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Toggle", 3 | "label": "A label for a toggle", 4 | "id": "toggle_element", 5 | "checked": false 6 | } 7 | -------------------------------------------------------------------------------- /src/scss/utilities/_auto-grid.scss: -------------------------------------------------------------------------------- 1 | .auto-grid { 2 | display: grid; 3 | grid-template-columns: repeat(auto-fill, minmax(var(--auto-grid-min-size, 16rem), 1fr)); 4 | gap: 1rem; 5 | padding: 0; 6 | } 7 | -------------------------------------------------------------------------------- /src/_data/navigation.json: -------------------------------------------------------------------------------- 1 | { 2 | "items": [ 3 | { 4 | "text": "Home", 5 | "url": "/" 6 | }, 7 | { 8 | "text": "About", 9 | "url": "/about/" 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /src/scss/utilities/_flow.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * FLOW 3 | * Applies a margin to sibling elements based on a --flow-space custom property. 4 | */ 5 | .flow > * + * { 6 | margin-top: var(--flow-space, get-size('600')); 7 | } 8 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 90, 3 | "tabWidth": 2, 4 | "singleQuote": true, 5 | "bracketSpacing": false, 6 | "quoteProps": "consistent", 7 | "trailingComma": "none", 8 | "arrowParens": "avoid" 9 | } 10 | -------------------------------------------------------------------------------- /src/_includes/layouts/page.njk: -------------------------------------------------------------------------------- 1 | {% extends "layouts/base.njk" %} 2 | 3 | {% block content %} 4 |
5 |

{{ title }}

6 | {{ content | safe }} 7 |
8 | {% endblock %} 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Misc 2 | *.log 3 | npm-debug.* 4 | *.scssc 5 | *.log 6 | *.swp 7 | .DS_Store 8 | Thumbs.db 9 | .sass-cache 10 | .env 11 | .cache 12 | 13 | # Node modules and output 14 | node_modules 15 | dist 16 | src/_includes/css 17 | .vscode 18 | -------------------------------------------------------------------------------- /src/_data/global.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | random() { 3 | const segment = () => { 4 | return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); 5 | }; 6 | return `${segment()}-${segment()}-${segment()}`; 7 | } 8 | }; 9 | -------------------------------------------------------------------------------- /src/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Base Project' 3 | metaDesc: 'Don’t forget the meta desc Maecenas sed diam eget risus varius blandit sit amet non magna. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.' 4 | layout: 'layouts/home.njk' 5 | --- 6 | -------------------------------------------------------------------------------- /src/scss/utilities/_visually-hidden.scss: -------------------------------------------------------------------------------- 1 | .visually-hidden { 2 | border: 0; 3 | clip: rect(0 0 0 0); 4 | height: auto; 5 | margin: 0; 6 | overflow: hidden; 7 | padding: 0; 8 | position: absolute; 9 | width: 1px; 10 | white-space: nowrap; 11 | } 12 | -------------------------------------------------------------------------------- /src/_includes/layouts/home.njk: -------------------------------------------------------------------------------- 1 | {% extends "layouts/base.njk" %} 2 | 3 | {% block content %} 4 |
5 |

Homepage

6 |

This could be a lander with info on how to get started working in the pattern library etc.

7 |
8 | {% endblock %} 9 | -------------------------------------------------------------------------------- /src/scss/blocks/_swatch.scss: -------------------------------------------------------------------------------- 1 | .swatch { 2 | background: white; 3 | border: 1px solid; 4 | 5 | > * { 6 | padding: 1rem; 7 | } 8 | 9 | &__sample { 10 | aspect-ratio: 16/9; 11 | } 12 | 13 | h2, 14 | h3 { 15 | text-transform: capitalize; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/scss/utilities/_wrapper.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * WRAPPER 3 | * Sets a max width, adds a consisten gutter and horizontally 4 | * centers the contents 5 | */ 6 | .wrapper { 7 | max-width: 60rem; 8 | padding: 0 get-size('500'); 9 | margin-left: auto; 10 | margin-right: auto; 11 | position: relative; 12 | } 13 | -------------------------------------------------------------------------------- /src/scss/blocks/_code-sample.scss: -------------------------------------------------------------------------------- 1 | .code-sample { 2 | border: 1px solid; 3 | background: white; 4 | padding: 1em; 5 | 6 | code { 7 | font-size: 1.2em; 8 | text-align: left; 9 | word-spacing: normal; 10 | word-break: normal; 11 | word-wrap: normal; 12 | tab-size: 2; 13 | hyphens: none; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/scss/blocks/_side-nav.scss: -------------------------------------------------------------------------------- 1 | .side-nav { 2 | border-top: 1px solid; 3 | padding: 0; 4 | 5 | a { 6 | display: block; 7 | padding: get-size('300') get-size('500'); 8 | background: white; 9 | text-decoration: none; 10 | font-weight: bold; 11 | } 12 | 13 | li { 14 | border-bottom: 1px solid; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/patterns/toggle-switch/toggle-switch.njk: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /src/typography.njk: -------------------------------------------------------------------------------- 1 | {% extends "layouts/base.njk" %} 2 | {% set title = 'Typography' %} 3 | 4 | {% block content %} 5 | 6 |
7 |

{{ title }}

8 |

Font sizes

9 | {% for item in tokens.sizes %} 10 |

Size item: {{ item.value }}

11 | {% endfor %} 12 |
13 | 14 | {% endblock %} 15 | -------------------------------------------------------------------------------- /src/filters/markdown-filter.js: -------------------------------------------------------------------------------- 1 | const markdown = require('markdown-it'); 2 | const stripIndent = require('strip-indent'); 3 | const renderer = new markdown(); 4 | 5 | module.exports = (content = '') => { 6 | const trimmedContent = stripIndent(content); 7 | 8 | return content.split('\n').length > 1 9 | ? renderer.render(trimmedContent) 10 | : renderer.renderInline(trimmedContent); 11 | }; 12 | -------------------------------------------------------------------------------- /src/about.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'About' 3 | layout: 'layouts/page.njk' 4 | --- 5 | 6 | Maecenas sed diam eget risus varius blandit sit amet non magna. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Nullam id dolor id nibh ultricies vehicula ut id elit. Curabitur blandit tempus porttitor. Vestibulum id ligula porta felis euismod semper. 7 | -------------------------------------------------------------------------------- /src/patterns/button/docs.md: -------------------------------------------------------------------------------- 1 | Nulla vitae elit libero, a pharetra augue. Sed posuere consectetur est at lobortis. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. 2 | 3 | Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Vestibulum id ligula porta felis euismod semper. Nulla vitae elit libero, a pharetra augue. Donec sed odio dui. 4 | -------------------------------------------------------------------------------- /gulp-tasks/fonts.js: -------------------------------------------------------------------------------- 1 | const {dest, src} = require('gulp'); 2 | const GetGoogleFonts = require('get-google-fonts'); 3 | 4 | const fonts = async () => { 5 | // Setup of the library instance by setting where we want 6 | // the output to go. CSS is relative to output font directory 7 | const instance = new GetGoogleFonts({ 8 | outputDir: './dist/fonts', 9 | cssFile: './fonts.css' 10 | }); 11 | 12 | // Grabs fonts and CSS from google and puts in the dist folder 13 | const result = await instance.download( 14 | 'https://fonts.googleapis.com/css2?family=Inter:wght@400;700;900&display=swap' 15 | ); 16 | 17 | return result; 18 | }; 19 | 20 | module.exports = fonts; 21 | -------------------------------------------------------------------------------- /src/scss/utilities/_sidebar.scss: -------------------------------------------------------------------------------- 1 | .sidebar { 2 | display: flex; 3 | flex-wrap: wrap; 4 | gap: get-size('500'); 5 | min-height: 100vh; 6 | } 7 | 8 | .sidebar > * { 9 | flex-basis: 14rem; 10 | flex-grow: 1; 11 | padding: get-size('700') 0; 12 | } 13 | 14 | .sidebar > :last-child { 15 | flex-basis: 0; 16 | flex-grow: 999; 17 | min-width: calc(50% - #{get-size('500')}); 18 | } 19 | 20 | .sidebar > :first-child { 21 | outline: 1px solid get-color('dark'); 22 | max-width: 20rem; 23 | } 24 | 25 | .sidebar > :first-child h2 { 26 | --flow-space: 2rem; 27 | padding-inline-start: get-size('500'); 28 | } 29 | 30 | .sidebar > :first-child h2 + * { 31 | --flow-space: 0.5rem; 32 | } 33 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Project base for Eleventy Sites 2 | 3 | Includes static page template and home page. Also includes gulp setup for SCSS, fonts and images. 4 | 5 |

Please don’t submit issues or PRs. I’m just sharing this for people that might want a decent starter. This isn’t open source: just free. Thanks.

6 | 7 | ℹ️ If you want to learn how it works, go ahead and take my [Eleventy course](//swop.link/11ty) 8 | 9 | ## Getting started 10 | 11 | Ideally, you’ll be using an LTS version of Node JS and if in Windows, the WSL setup because it works better with gulp. 12 | 13 | 1. Run `npm install` 14 | 2. Run `npm start` to run locally 15 | 3. Run `npm run production` to do a prod build 16 | -------------------------------------------------------------------------------- /gulp-tasks/images.js: -------------------------------------------------------------------------------- 1 | const {dest, src} = require('gulp'); 2 | const imagemin = require('gulp-imagemin'); 3 | 4 | // Grabs all images, runs them through imagemin 5 | // and plops them in the dist folder 6 | const images = cb => { 7 | // We have specific configs for jpeg and png files to try 8 | // to really pull down asset sizes 9 | return src('./src/images/**/*') 10 | .pipe( 11 | imagemin( 12 | [ 13 | imagemin.mozjpeg({quality: 60, progressive: true}), 14 | imagemin.optipng({optimizationLevel: 5, interlaced: null}) 15 | ], 16 | { 17 | silent: true 18 | } 19 | ) 20 | ) 21 | .pipe(dest('./dist/images')) 22 | .on('done', cb); 23 | }; 24 | 25 | module.exports = images; 26 | -------------------------------------------------------------------------------- /.eleventy.js: -------------------------------------------------------------------------------- 1 | // Create a global base directory variable for easier includes 2 | global.__basedir = __dirname; 3 | 4 | const markdownFilter = require('./src/filters/markdown-filter.js'); 5 | 6 | module.exports = config => { 7 | // Tell 11ty to use the .eleventyignore and ignore our .gitignore file 8 | config.setUseGitIgnore(false); 9 | 10 | config.addCollection('patterns', collection => { 11 | return collection.getFilteredByGlob('./src/patterns/**/*.njk'); 12 | }); 13 | 14 | config.addFilter('markdownFilter', markdownFilter); 15 | 16 | return { 17 | markdownTemplateEngine: 'njk', 18 | dataTemplateEngine: 'njk', 19 | htmlTemplateEngine: 'njk', 20 | dir: { 21 | input: 'src', 22 | output: 'dist' 23 | } 24 | }; 25 | }; 26 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "11ty-base-no-blog", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": ".eleventy.js", 6 | "scripts": { 7 | "start": "npx gulp && concurrently 'npx gulp watch' 'npx eleventy --serve --quiet'", 8 | "production": "NODE_ENV=production npx gulp && NODE_ENV=production eleventy" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "@11ty/eleventy": "^0.12.1", 15 | "@11ty/eleventy-cache-assets": "^2.1.0", 16 | "concurrently": "^6.0.2", 17 | "get-google-fonts": "^1.2.2", 18 | "gorko": "^0.3.0", 19 | "gulp": "^4.0.2", 20 | "gulp-clean-css": "^4.3.0", 21 | "gulp-imagemin": "^7.1.0", 22 | "gulp-sass": "^4.1.0", 23 | "sass": "^1.32.11" 24 | }, 25 | "devDependencies": { 26 | "prettier": "^2.2.1" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/colors.njk: -------------------------------------------------------------------------------- 1 | {% extends "layouts/base.njk" %} 2 | {% set title = 'Colors' %} 3 | 4 | {% block content %} 5 | 6 |
7 |

{{ title }}

8 | 26 |
27 | 28 | {% endblock %} 29 | -------------------------------------------------------------------------------- /src/_includes/partials/pagination.njk: -------------------------------------------------------------------------------- 1 | {# Only renders this section if there are links to render #} 2 | {% if pagination.href.next or pagination.href.previous %} 3 | 19 | {% endif %} 20 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | const {parallel, watch} = require('gulp'); 2 | 3 | // Pull in each task 4 | const fonts = require('./gulp-tasks/fonts.js'); 5 | const images = require('./gulp-tasks/images.js'); 6 | const sass = require('./gulp-tasks/sass.js'); 7 | 8 | // Set each directory and contents that we want to watch and 9 | // assign the relevant task. `ignoreInitial` set to true will 10 | // prevent the task being run when we run `gulp watch`, but it 11 | // will run when a file changes. 12 | const watcher = () => { 13 | watch('./src/images/**/*', {ignoreInitial: true}, images); 14 | watch('./src/scss/**/*.scss', {ignoreInitial: true}, sass); 15 | }; 16 | 17 | // The default (if someone just runs `gulp`) is to run each task in parrallel 18 | exports.default = parallel(fonts, images, sass); 19 | 20 | // This is our watcher task that instructs gulp to watch directories and 21 | // act accordingly 22 | exports.watch = watcher; 23 | -------------------------------------------------------------------------------- /src/_includes/prototype.js: -------------------------------------------------------------------------------- 1 | const frameContext = location.pathname.replace(/\//g, '-'); 2 | 3 | const frameKeys = { 4 | width: `${frameContext}:frame-width`, 5 | height: `${frameContext}:frame-height` 6 | }; 7 | 8 | const frameWidth = localStorage.getItem(frameKeys.width); 9 | const frameHeight = localStorage.getItem(frameKeys.height); 10 | 11 | if (frameWidth) { 12 | document.documentElement.style.setProperty('--frame-width', frameWidth); 13 | } 14 | 15 | if (frameHeight) { 16 | document.documentElement.style.setProperty('--frame-height', frameHeight); 17 | } 18 | 19 | document.querySelectorAll('iframe').forEach(item => 20 | item.contentWindow.addEventListener('resize', evt => { 21 | const rects = item.getClientRects()[0]; 22 | const itemWidth = rects.width; 23 | const itemHeight = rects.height; 24 | 25 | document.documentElement.style.setProperty('--frame-width', `${itemWidth}px`); 26 | document.documentElement.style.setProperty('--frame-height', `${itemHeight}px`); 27 | localStorage.setItem(frameKeys.width, `${itemWidth}px`); 28 | localStorage.setItem(frameKeys.height, `${itemHeight}px`); 29 | }) 30 | ); 31 | -------------------------------------------------------------------------------- /src/patterns/toggle-switch/docs.md: -------------------------------------------------------------------------------- 1 | Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Aenean lacinia bibendum nulla sed consectetur. Curabitur blandit tempus porttitor. Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Maecenas sed diam eget risus varius blandit sit amet non magna. 2 | 3 | Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Sed posuere consectetur est at lobortis. Nullam quis risus eget urna mollis ornare vel eu leo. 4 | 5 | Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Maecenas faucibus mollis interdum. Vestibulum id ligula porta felis euismod semper. Maecenas sed diam eget risus varius blandit sit amet non magna. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. 6 | -------------------------------------------------------------------------------- /src/scss/_reset.scss: -------------------------------------------------------------------------------- 1 | /* Box sizing rules */ 2 | *, 3 | *::before, 4 | *::after { 5 | box-sizing: border-box; 6 | } 7 | 8 | /* Remove default margin */ 9 | body, 10 | h1, 11 | h2, 12 | h3, 13 | h4, 14 | p, 15 | figure, 16 | blockquote, 17 | dl, 18 | dd { 19 | margin: 0; 20 | } 21 | 22 | /* Remove list styles on ul, ol elements with a list role, which suggests default styling will be removed */ 23 | ul[role='list'], 24 | ol[role='list'] { 25 | list-style: none; 26 | } 27 | 28 | /* Set core root defaults */ 29 | html:focus-within { 30 | scroll-behavior: smooth; 31 | } 32 | 33 | /* Set core body defaults */ 34 | body { 35 | min-height: 100vh; 36 | text-rendering: optimizeSpeed; 37 | line-height: 1.5; 38 | } 39 | 40 | /* A elements that don't have a class get default styles */ 41 | a:not([class]) { 42 | text-decoration-skip-ink: auto; 43 | } 44 | 45 | /* Make images easier to work with */ 46 | img, 47 | picture { 48 | max-width: 100%; 49 | display: block; 50 | } 51 | 52 | /* Inherit fonts for inputs and buttons */ 53 | input, 54 | button, 55 | textarea, 56 | select { 57 | font: inherit; 58 | } 59 | 60 | @media (prefers-reduced-motion: reduce) { 61 | html:focus-within { 62 | scroll-behavior: auto; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/_data/helpers.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | getLinkActiveState(itemUrl, pageUrl) { 3 | let response = ''; 4 | 5 | if (itemUrl === pageUrl) { 6 | response = ' aria-current="page"'; 7 | } 8 | 9 | if (itemUrl.length > 1 && pageUrl.indexOf(itemUrl) === 0) { 10 | response += ' data-state="active"'; 11 | } 12 | 13 | return response; 14 | }, 15 | 16 | getSiblingContent(collection, item, limit = 3, random = true) { 17 | let filteredItems = collection.filter(x => x.url !== item.url); 18 | 19 | if (random) { 20 | let counter = filteredItems.length; 21 | 22 | while (counter > 0) { 23 | // Pick a random index 24 | let index = Math.floor(Math.random() * counter); 25 | 26 | counter--; 27 | 28 | let temp = filteredItems[counter]; 29 | 30 | // Swap the last element with the random one 31 | filteredItems[counter] = filteredItems[index]; 32 | filteredItems[index] = temp; 33 | } 34 | } 35 | 36 | // Lastly, trim to length 37 | if (limit > 0) { 38 | filteredItems = filteredItems.slice(0, limit); 39 | } 40 | 41 | return filteredItems; 42 | }, 43 | 44 | filterCollectionByKeys(collection, keys) { 45 | return collection.filter(x => keys.includes(x.data.key)); 46 | } 47 | }; 48 | -------------------------------------------------------------------------------- /src/_data/patterns.js: -------------------------------------------------------------------------------- 1 | const nunjucks = require('nunjucks'); 2 | const fs = require('fs'); 3 | const path = require('path'); 4 | 5 | module.exports = { 6 | navItems(collection) { 7 | return collection.filter(x => !x.inputPath.includes('variants')); 8 | }, 9 | getVariants(item, collection) { 10 | // If the item itself is a variant, return early. 11 | if (item.filePathStem.includes('variants')) { 12 | return; 13 | } 14 | 15 | const basePath = item.filePathStem 16 | .split('/') 17 | .slice(0, 3) 18 | .join('/'); 19 | 20 | return collection.filter( 21 | x => 22 | x.filePathStem.indexOf(basePath) === 0 && 23 | x.filePathStem.includes('variants') 24 | ); 25 | }, 26 | render(item) { 27 | const markup = fs.readFileSync( 28 | path.resolve(__basedir, item.inputPath), 29 | 'utf8' 30 | ); 31 | 32 | return nunjucks.renderString(markup, {data: item.data}); 33 | }, 34 | renderSource(item) { 35 | const markup = fs.readFileSync( 36 | path.resolve(__basedir, item.inputPath), 37 | 'utf8' 38 | ); 39 | 40 | return markup; 41 | }, 42 | getDocs(item) { 43 | const docsPath = path.join(__basedir, path.dirname(item.inputPath), 'docs.md'); 44 | 45 | if (!fs.existsSync(docsPath)) { 46 | return null; 47 | } 48 | 49 | const docsContent = fs.readFileSync(docsPath, 'utf8'); 50 | 51 | return docsContent; 52 | } 53 | }; 54 | -------------------------------------------------------------------------------- /src/_data/tokens.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors": [ 3 | { 4 | "name": "dark", 5 | "value": "#121111", 6 | "customProp": "var(--color-dark)", 7 | "sass": "get-color('dark')" 8 | }, 9 | { 10 | "name": "primary", 11 | "value": "#3740ff", 12 | "customProp": "var(--color-primary)", 13 | "sass": "get-color('primary')" 14 | }, 15 | { 16 | "name": "primary dark", 17 | "value": "#272eb5", 18 | "customProp": "var(--color-primary-dark)", 19 | "sass": "get-color('primary-dark')" 20 | }, 21 | { 22 | "name": "primary extra light", 23 | "value": "#e8f0fe", 24 | "customProp": "var(--color-primary-x-light)", 25 | "sass": "get-color('primary-x-light')" 26 | }, 27 | { 28 | "name": "secondary", 29 | "value": "#2fc1ff", 30 | "customProp": "var(--color-secondary)", 31 | "sass": "get-color('color-secondary')" 32 | } 33 | ], 34 | "sizes": [ 35 | { 36 | "key": "300", 37 | "value": 0.75 38 | }, 39 | { 40 | "key": "400", 41 | "value": 1 42 | }, 43 | { 44 | "key": "500", 45 | "value": 1.33 46 | }, 47 | { 48 | "key": "600", 49 | "value": 1.77 50 | }, 51 | { 52 | "key": "700", 53 | "value": 2.36 54 | }, 55 | { 56 | "key": "800", 57 | "value": 3.15 58 | }, 59 | { 60 | "key": "900", 61 | "value": 4.2 62 | } 63 | ] 64 | } 65 | -------------------------------------------------------------------------------- /src/_includes/partials/meta-info.njk: -------------------------------------------------------------------------------- 1 | {% set pageTitle = title + ' - ' + site.name %} 2 | 3 | {# We don't want any duplication. This is likely for the homepage #} 4 | {% if site.name === title %} 5 | {% set pageTitle = title %} 6 | {% endif %} 7 | 8 | {% set siteTitle = site.name %} 9 | {% set currentUrl = site.url + page.url %} 10 | 11 | {# If the page’s frontmatter has specific metaTitle and/or metaDesc items, switch 12 | them into the mix #} 13 | {% if metaTitle %} 14 | {% set pageTitle = metaTitle %} 15 | {% endif %} 16 | 17 | {% if not metaDesc %} 18 | {% set metaDesc = summary %} 19 | {% endif %} 20 | 21 | 22 | {{ pageTitle }} 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | {% if socialImage %} 31 | 32 | 33 | 34 | 35 | 36 | {% endif %} 37 | 38 | {% if metaDesc %} 39 | 40 | 41 | 42 | {% endif %} 43 | -------------------------------------------------------------------------------- /gulp-tasks/sass.js: -------------------------------------------------------------------------------- 1 | const {dest, src} = require('gulp'); 2 | const cleanCSS = require('gulp-clean-css'); 3 | const sassProcessor = require('gulp-sass'); 4 | 5 | // We want to be using canonical Sass, rather than node-sass 6 | sassProcessor.compiler = require('sass'); 7 | 8 | // Flags wether we compress the output etc 9 | const isProduction = process.env.NODE_ENV === 'production'; 10 | 11 | // An array of outputs that should be sent over to includes 12 | const criticalStyles = ['critical.scss']; 13 | 14 | // Takes the arguments passed by `dest` and determines where the output file goes 15 | const calculateOutput = ({history}) => { 16 | // By default, we want a CSS file in our dist directory, so the 17 | // HTML can grab it with a 18 | let response = './dist/css'; 19 | 20 | // Get everything after the last slash 21 | const sourceFileName = /[^/]*$/.exec(history[0])[0]; 22 | 23 | // If this is critical CSS though, we want it to go 24 | // to the _includes directory, so nunjucks can include it 25 | // directly in a 12 | 13 | {# Add facility for pages to delare an array of critical styles #} 14 | {% if pageCriticalStyles %} 15 | {% for item in pageCriticalStyles %} 16 | 17 | {% endfor %} 18 | {% endif %} 19 | 20 | 21 | 22 | {# Add facility for pages to declare an array of stylesheet paths #} 23 | {% if pageStylesheets %} 24 | {% for item in pageStylesheets %} 25 | 26 | {% endfor %} 27 | {% endif %} 28 | 29 | 30 | {% include "partials/site-head.njk" %} 31 | 32 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /src/scss/_config.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * BASE SIZE 3 | * All calculations are based on this. It’s recommended that 4 | * you keep it at 1rem because that is the root font size. You 5 | * can set it to whatever you like and whatever unit you like. 6 | */ 7 | $gorko-base-size: 1rem; 8 | 9 | /** 10 | * SIZE SCALE 11 | * This is a Perfect Fourth scale that powers all the utilities that 12 | * it is relevant for (font-size, margin, padding). All items are 13 | * calcuated off the base size, so change that and cascade across 14 | * your whole project. 15 | */ 16 | $gorko-size-scale: ( 17 | '300': $gorko-base-size * 0.75, 18 | '400': $gorko-base-size, 19 | '500': $gorko-base-size * 1.33, 20 | '600': $gorko-base-size * 1.77, 21 | '700': $gorko-base-size * 2.36, 22 | '800': $gorko-base-size * 3.15, 23 | '900': $gorko-base-size * 4.2, 24 | 'major': $gorko-base-size * 5.6 25 | ); 26 | 27 | /** 28 | * COLORS 29 | * Colors are shared between backgrounds and text by default. 30 | * You can also use them to power borders, fills or shadows, for example. 31 | */ 32 | $gorko-colors: ( 33 | 'dark': #38445b, 34 | 'dark-shade': #263147, 35 | 'dark-glare': #505c73, 36 | 'light': #efefef, 37 | 'light-shade': #fdfdfd, 38 | 'light-glare': #fdfbf3, 39 | 'primary': #513aa6 40 | ); 41 | 42 | /** 43 | * CORE CONFIG 44 | * This powers everything from utility class generation to breakpoints 45 | * to enabling/disabling pre-built components/utilities. 46 | */ 47 | $gorko-config: ( 48 | 'bg': ( 49 | 'items': $gorko-colors, 50 | 'output': 'standard', 51 | 'property': 'background' 52 | ), 53 | 'color': ( 54 | 'items': $gorko-colors, 55 | 'output': 'standard', 56 | 'property': 'color' 57 | ), 58 | 'flow-space': ( 59 | 'items': $gorko-size-scale, 60 | 'output': 'responsive', 61 | 'property': '--flow-space' 62 | ), 63 | 'font': ( 64 | 'items': ( 65 | 'base': 'sans-serif', 66 | 'sans': '"Inter", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif' 67 | ), 68 | 'output': 'standard', 69 | 'property': 'font-family' 70 | ), 71 | 'gap-top': ( 72 | 'items': $gorko-size-scale, 73 | 'output': 'responsive', 74 | 'property': 'margin-top' 75 | ), 76 | 'leading': ( 77 | 'items': ( 78 | 'loose': 1.7, 79 | 'tight': 1.3, 80 | 'flat': '1.1' 81 | ), 82 | 'output': 'standard', 83 | 'property': 'line-height' 84 | ), 85 | 'measure': ( 86 | 'items': ( 87 | 'micro': '10ch', 88 | 'compact': '30ch', 89 | 'short': '40ch', 90 | 'long': '65ch' 91 | ), 92 | 'output': 'responsive', 93 | 'property': 'max-width' 94 | ), 95 | 'text': ( 96 | 'items': $gorko-size-scale, 97 | 'output': 'responsive', 98 | 'property': 'font-size' 99 | ), 100 | 'weight': ( 101 | 'items': ( 102 | 'normal': 400, 103 | 'bold': 900 104 | ), 105 | 'output': 'standard', 106 | 'property': 'font-weight' 107 | ), 108 | 'breakpoints': ( 109 | 'md': '(min-width: 37em)', 110 | 'lg': '(min-width: 62em)' 111 | ) 112 | ); 113 | -------------------------------------------------------------------------------- /src/preview.njk: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Preview' 3 | pagination: 4 | data: collections.patterns 5 | size: 1 6 | addAllPagesToCollections: true 7 | alias: item 8 | permalink: '/preview/{{ item.fileSlug | slug }}/index.html' 9 | --- 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | {{ item.data.title }} - Preview 19 | 60 | 61 | 62 |
63 | {{ patterns.render(item) | safe }} 64 |
65 | 130 | 131 | 132 | --------------------------------------------------------------------------------