├── .gitignore ├── .nvmrc ├── LICENSE ├── README.md ├── _prose.yml ├── build.js ├── css ├── _columns.css ├── _list.css ├── _page.css ├── _vr-reset.css ├── _widths.css └── main.css ├── nodemon.json ├── package.json ├── preview.png ├── resume.pdf ├── source ├── 404.md ├── education.md ├── education │ └── owen-patterson.md ├── experience.md ├── experience │ ├── metacortex.md │ ├── nebuchadnezzar.md │ └── zion.md ├── index.md ├── person.yaml └── site.yaml ├── templates ├── collection.pug ├── components │ ├── columns.pug │ ├── experience.pug │ ├── footer.pug │ ├── links.pug │ └── section.pug ├── default.pug └── partials │ ├── head.pug │ └── header.pug └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | **/.DS_Store 3 | npm-debug.log 4 | _build 5 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 5 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 @lowmess (lowmess.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DEPRECATED 2 | 3 | This project has been deprecated. The [JSONResume](https://jsonresume.org/) project is a good alternative. 4 | 5 | --- 6 | 7 | # Metalsmith Resume 8 | 9 | ![Preview of the default generated Resume](preview.png) 10 | 11 | Listen, writing resumes sucks. Microsoft Word isn't great at layout, Adobe InDesign isn't the best for content editing, and neither excel at managing information. I wanted to change that for myself, so I made my resume as a [Metalsmith](http://metalsmith.io) minisite. Then I made a better one to give away to everyone else (this thing you're looking at now). The math is simple: `markdown + YAML + git > those other things I just mentioned`. 12 | 13 | ## Editing 14 | 15 | 1. Fork this repo 16 | 2. Open the project on [Prose](http://prose.io) 17 | 3. Edit and add files 18 | 4. ??? 19 | 5. Profit (hopefully literally) 20 | 21 | ### Adding Experiences 22 | 23 | The most important part of any resume is, of course, showing off your bad self. The whole point of this project is to make that easier. So anyways, jobs live in the [`/experience`](/source/experience) subdirectory and schools in the [`/education`](/source/education) one. Each is it's own `.md` file with YAML metadata. 24 | 25 | #### Metadata 26 | 27 | As mentioned above, the easiest way to edit your resume is with [Prose](http://prose.io). Each job/school is expecting a few metadata fields, and Prose shows all those fields to you. I'm not gonna list them all out here for you, so the second easiest way is to just look at [an](/source/experience/zion.md) [existing](/source/experience/nebuchadnezzar.md) [experience](/source/education/owen-patterson.md) and copy that. 28 | 29 | ### Personal Information 30 | 31 | The [`person.yaml`](/source/person.yaml) file is your key to making this resume your own. That's it for this section. ¯\\\_(ツ)\_/¯ 32 | 33 | ### Site Settings 34 | 35 | You can adjust display and styling settings in the [`site.yaml`](/source/site.yaml) file. 36 | 37 | #### Set Number of Items to Show 38 | 39 | The `jobs` and `schools` variables let you adjust the number of jobs & schools that are shown on the resume. I'll let the surprise settle in. Setting a variable to zero will hide the section completely. Full job & school histories are available at `/experience` & `/education`, respectively, regardless of these settings. 40 | 41 | #### Theme Color 42 | 43 | You can set your theme with the `theme` variable. I'll one again wait to let the shock wash over you. It will automagically™ check if your theme color has a high enough contrast ratio against white and adjust the styles accordingly. For best results, choose a color that has a color contrast ratio of at least 3.5 with white. [Hey look, a calculator](http://leaverou.github.io/contrast-ratio/)! 44 | 45 | #### Print Styles 46 | 47 | There is a setting called `printstyles`. This is probably a bad name. I should update this name. 🤔 Anyways, what it does is it makes everything black and white when you try and print the resume. 48 | 49 | ## Generating a PDF 50 | 51 | ...is a much bigger headache than it would seem. You can always `cmd + p` and use the browser to save a PDF, but I built a nice generation function for you anyways. Unfortunately, it's a little jank right now. It uses [node-html-pdf](https://github.com/marcbachmann/node-html-pdf), which in turn uses [PhantomJS](http://phantomjs.org/), which causes some weird text zoom issue. So I have to: 52 | 53 | 1. Rebuild the site with a print environment flag that applies a global font de-scalification 54 | 3. Do the whole PDF generation thing (the whole point of this exercise) 55 | 4. Rebuild the site *without* the print flag 56 | 57 | ...it takes like, I dunno, 5 or 10 seconds? Which feels like *forever*. Anyways, you can generate a PDF with `npm run pdf` (or, again, just push `cmd + p` when you have it up and running). 58 | 59 | ## Development 60 | 61 | ### Installation 62 | 63 | ``` 64 | git clone https://github.com/lowmess/metalsmith-resume.git 65 | cd metalsmith-resume 66 | npm i 67 | ``` 68 | 69 | ### Local Server 70 | 71 | [Browsersync](https://www.browsersync.io/) & [nodemon](http://nodemon.io/) is a match made in heaven. Luckily for you, it's already all set up! Just run `npm start` from the root directory of your repo and begin hacking away. 72 | 73 | ### Building 74 | 75 | `npm run build` will build the resume site for you into the `_build` directory. Pretty straightforward. 76 | 77 | Oh yeah and `npm run build:minify` will build, umm, minified files. I'd recommend doing that before you deploy. 78 | 79 | ### Styling 80 | 81 | This project uses [Tachyons](http://tachyons.io) (with a few custom classes added in for good measure). All modules are included in the build, which is then run through a few performance-enhancing PostCSS plugins (PEPP'rd) like [UnCSS](https://github.com/giakki/uncss) & [cssnano](http://cssnano.co/). As of right now, all the loaded CSS is [~3kb](http://cssstats.com/stats?url=http%3A%2F%2Fmetalsmith-resume.lowmess.com&ua=Browser%20Default), and that's pretty damn cool.[1] 🤓 82 | 83 | ## Contributing 84 | 85 | Contributions are welcome and encouraged: 86 | 87 | 1. Fork the project 88 | 2. Make your changes 89 | 3. Open a PR that has a descriptive name (or a robust description) 90 | 4. Feel good about yourself 🎉 91 | 92 | *** 93 | 94 | [1] For reference, this long-as-hell README is, like, almost five goddamn KBs. 95 | -------------------------------------------------------------------------------- /_prose.yml: -------------------------------------------------------------------------------- 1 | prose: 2 | rooturl: 'source' 3 | ignore: ['index.md', '404.md', 'experience.md', 'education.md'] 4 | media: 'source/images' 5 | metadata: 6 | 'source/experience': 7 | - name: 'title' 8 | field: 9 | element: 'text' 10 | label: 'Job Title' 11 | placeholder: 'Software Programmer' 12 | type: 'text' 13 | - name: 'subtitle' 14 | field: 15 | element: 'text' 16 | label: 'Workplace' 17 | placeholder: 'MetaCortex' 18 | type: 'text' 19 | - name: 'url' 20 | field: 21 | element: 'text' 22 | label: 'Workplace website' 23 | placeholder: 'http://metacortex.info' 24 | type: 'text' 25 | - name: 'startDate' 26 | field: 27 | element: 'text' 28 | label: 'Start Date' 29 | help: 'YYYY-MM-DD' 30 | placeholder: '1997-09-13' 31 | type: 'text' 32 | - name: 'endDate' 33 | field: 34 | element: 'text' 35 | label: 'End Date' 36 | help: 'leave blank for current position' 37 | placeholder: '1999-03-31' 38 | type: 'text' 39 | - name: 'location' 40 | field: 41 | element: 'text' 42 | label: 'Location' 43 | placeholder: 'Capitol City, USA' 44 | type: 'text' 45 | 'source/education': 46 | - name: 'title' 47 | field: 48 | element: 'text' 49 | label: 'Degree' 50 | placeholder: 'High School Diploma' 51 | type: 'text' 52 | - name: 'subtitle' 53 | field: 54 | element: 'text' 55 | label: 'Institution' 56 | placeholder: 'Owen Patterson H.S.' 57 | type: 'text' 58 | - name: 'url' 59 | field: 60 | element: 'text' 61 | label: 'Institution website' 62 | placeholder: 'http://owenpattersonhs.edu' 63 | type: 'text' 64 | - name: 'startDate' 65 | field: 66 | element: 'text' 67 | label: 'Start Date' 68 | help: 'YYYY-MM-DD' 69 | placeholder: '1985-08-10' 70 | type: 'text' 71 | - name: 'endDate' 72 | field: 73 | element: 'text' 74 | label: 'End Date' 75 | help: 'leave blank for current' 76 | placeholder: '1989-05-30' 77 | type: 'text' 78 | - name: 'location' 79 | field: 80 | element: 'text' 81 | label: 'Location' 82 | placeholder: 'Capitol City, USA' 83 | type: 'text' 84 | -------------------------------------------------------------------------------- /build.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs') 2 | // Metalsmith 3 | var Metalsmith = require('metalsmith') 4 | var permalinks = require('metalsmith-permalinks') 5 | var metadata = require('metalsmith-metadata') 6 | var collections = require('metalsmith-collections') 7 | var markdown = require('metalsmith-markdownit') 8 | var layouts = require('metalsmith-layouts') 9 | var minify = require('metalsmith-html-minifier') 10 | var defaults = require('metalsmith-default-values') 11 | var drafts = require('metalsmith-drafts') 12 | // PostCSS 13 | var postcss = require('postcss') 14 | // PDF 15 | var pdf = require('html-pdf') 16 | 17 | /* Metalsmith 18 | ******************************************************************************/ 19 | 20 | var siteBuild = Metalsmith(__dirname) 21 | .source('source') 22 | .destination('_build') 23 | .use(metadata({ 24 | 'site': 'site.yaml', 25 | 'person': 'person.yaml' 26 | })) 27 | .use(drafts()) 28 | .use(collections({ 29 | education: { 30 | pattern: 'education/**/*.md', 31 | sortBy: 'startDate', 32 | reverse: true 33 | }, 34 | experience: { 35 | pattern: 'experience/**/*.md', 36 | sortBy: 'startDate', 37 | reverse: true 38 | }, 39 | pages: { 40 | pattern: '*.md' 41 | } 42 | })) 43 | .use(defaults([{ 44 | pattern: '*/**/*.md', 45 | defaults: { 46 | draft: true 47 | } 48 | }])) 49 | // HTML 50 | .use(markdown({ 51 | html: true, 52 | xhtmlOut: true, 53 | typographer: true, 54 | linkify: true 55 | })) 56 | .use(permalinks({ 57 | pattern: ':title', 58 | relative: false 59 | })) 60 | .use(layouts({ 61 | engine: 'pug', 62 | pretty: true, 63 | moment: require('moment'), 64 | contrast: require('get-contrast'), 65 | directory: 'templates', 66 | default: 'default.pug', 67 | pattern: '**/*.html' 68 | })) 69 | .use(drafts()) 70 | 71 | if (process.env.NODE_ENV === 'production') { 72 | siteBuild.use(minify()) 73 | } 74 | 75 | siteBuild.build(function (err) { 76 | if (err) { 77 | console.log(err) 78 | } else { 79 | console.log('Metalsmith complete!\n') 80 | stylesheets() 81 | if (process.env.NODE_ENV === 'print') { 82 | print() 83 | } 84 | } 85 | }) 86 | 87 | /* PostCSS 88 | ******************************************************************************/ 89 | 90 | function stylesheets () { 91 | var css = fs.readFileSync('css/main.css', 'utf-8') 92 | 93 | var plugins = [ 94 | require('postcss-import'), 95 | require('postcss-nested'), 96 | require('postcss-custom-properties'), 97 | require('postcss-custom-media'), 98 | require('postcss-color-function'), 99 | require('postcss-focus'), 100 | require('autoprefixer')({ 101 | browsers: ['last 2 versions', '> 5%'] 102 | }), 103 | require('css-mqpacker'), 104 | require('cssnano') 105 | ] 106 | 107 | if (process.env.NODE_ENV === 'production') { 108 | plugins.push( 109 | require('postcss-uncss')({ 110 | html: ['_build/**/*.html'] 111 | }) 112 | ) 113 | } 114 | 115 | postcss(plugins) 116 | .process(css, { 117 | from: 'css/main.css', 118 | to: '_build/css/main.css', 119 | map: { inline: false } 120 | }) 121 | .then(function (result) { 122 | if (result.warnings()) { 123 | result.warnings().forEach(warn => { 124 | console.warn(warn.toString()) 125 | }) 126 | } 127 | fs.mkdirSync('_build/css') 128 | fs.writeFileSync('_build/css/main.css', result.css, 'utf-8') 129 | if (result.map) fs.writeFileSync('_build/css/main.css.map', result.map, 'utf-8') 130 | console.log('PostCSS Complete!\n') 131 | }) 132 | } 133 | 134 | /* PDF 135 | ******************************************************************************/ 136 | 137 | function print () { 138 | var html = fs.readFileSync('_build/index.html', 'utf8') 139 | var options = { 140 | height: '11in', 141 | width: '8.5in', 142 | type: 'pdf', 143 | base: 'http://localhost:8008' 144 | } 145 | 146 | var server = require('browser-sync').create() 147 | 148 | server.init({ 149 | server: '_build', 150 | port: 8008, 151 | open: false, 152 | ui: false 153 | }) 154 | 155 | pdf.create(html, options).toFile('resume.pdf', function (err, res) { 156 | if (err) return console.log(err) 157 | server.exit() 158 | console.log('\nPDF generation complete!\n') 159 | process.exit() 160 | }) 161 | } 162 | -------------------------------------------------------------------------------- /css/_columns.css: -------------------------------------------------------------------------------- 1 | /* Variables */ 2 | 3 | /* Spacing Scale - based on a ratio of 1:2 */ 4 | :root { 5 | --spacing-none: 0; 6 | --spacing-extra-small: 0.25rem; 7 | --spacing-small: 0.5rem; 8 | --spacing-medium: 1rem; 9 | --spacing-large: 2rem; 10 | --spacing-extra-large: 4rem; 11 | } 12 | /* 13 | COLUMNS 14 | 15 | A six step powers of two scale ranging from 0 to 4rem. 16 | Namespaces are composable and thus highly grockable - check the legend below 17 | 18 | Legend: 19 | 20 | cc = column-count 21 | cg = column-gap 22 | 23 | 0 = none 24 | 1 = 1st step in spacing scale 25 | 2 = 2nd step in spacing scale 26 | 3 = 3rd step in spacing scale 27 | 4 = 4th step in spacing scale 28 | 5 = 5th step in spacing scale 29 | 30 | */ 31 | 32 | @media print { 33 | .cc2-p { column-count: 2; } 34 | 35 | .cc3-p { column-count: 3; } 36 | 37 | .cc4-p { column-count: 4; } 38 | 39 | .cc5-p { column-count: 5; } 40 | 41 | .cc6-p { column-count: 6; } 42 | 43 | .cg0-p { column-gap: var(--spacing-none); } 44 | 45 | .cg1-p { column-gap: var(--spacing-extra-small); } 46 | 47 | .cg2-p { column-gap: var(--spacing-small); } 48 | 49 | .cg3-p { column-gap: var(--spacing-medium); } 50 | 51 | .cg4-p { column-gap: var(--spacing-large); } 52 | 53 | .cg5-p { column-gap: var(--spacing-extra-large); } 54 | } 55 | -------------------------------------------------------------------------------- /css/_list.css: -------------------------------------------------------------------------------- 1 | @custom-media --breakpoint-not-small screen and (min-width: 48em); 2 | @custom-media --breakpoint-medium screen and (min-width: 48em) and (max-width: 64em); 3 | @custom-media --breakpoint-large screen and (min-width: 64em); 4 | 5 | .list-inside { 6 | list-style-position: inside; 7 | } 8 | 9 | @media (--breakpoint-not-small) { 10 | .list-inside-ns { list-style-position: inside; } 11 | } 12 | 13 | @media (--breakpoint-medium) { 14 | .list-inside-m { list-style-position: inside; } 15 | } 16 | 17 | @media (--breakpoint-large) { 18 | .list-inside-l { list-style-position: inside; } 19 | } 20 | 21 | @media print { 22 | .list-inside-p { list-style-position: inside; } 23 | } 24 | -------------------------------------------------------------------------------- /css/_page.css: -------------------------------------------------------------------------------- 1 | :root { 2 | /* Page Settings: */ 3 | --page-width: 8.5in; 4 | 5 | /* Colors from Tachyons */ 6 | --light-gray: #eeeeee; 7 | 8 | /* Spacing from Tachyons */ 9 | --spacing-extra-large: 4rem; 10 | } 11 | 12 | /* Media Queries */ 13 | @custom-media --breakpoint-page screen and (min-width: 8.5in); 14 | 15 | /* Styles */ 16 | 17 | .mw-page { max-width: var(--page-width); } 18 | 19 | @media (--breakpoint-page) { 20 | .mv-5-page { 21 | margin-top: var(--spacing-extra-large); 22 | margin-bottom: var(--spacing-extra-large); 23 | } 24 | 25 | .bg-light-gray-page { background-color: var(--light-gray); } 26 | 27 | .shadow-2-page { box-shadow: 0 0 8px 2px rgba(0, 0, 0, 0.2); } 28 | 29 | .db-page { display: block; } 30 | } 31 | 32 | @media print { 33 | @page { 34 | size: letter portrait; 35 | margin: 0; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /css/_vr-reset.css: -------------------------------------------------------------------------------- 1 | h1, h2, h3, h4, h5, h6, p, ul, ol, pre, table, blockquote, address { 2 | &:first-child { margin-top: 0; } 3 | 4 | &:last-child { margin-bottom: 0; } 5 | } 6 | -------------------------------------------------------------------------------- /css/_widths.css: -------------------------------------------------------------------------------- 1 | @custom-media --breakpoint-not-small screen and (min-width: 48em); 2 | @custom-media --breakpoint-medium screen and (min-width: 48em) and (max-width: 64em); 3 | @custom-media --breakpoint-large screen and (min-width: 64em); 4 | /* 5 | 6 | WIDTHS 7 | 8 | Base: 9 | w = width 10 | 11 | Modifiers 12 | -33 = literal value 33% 13 | -66 = literal value 66% 14 | 15 | Media Query Extensions: 16 | -ns = not-small 17 | -m = medium 18 | -l = large 19 | 20 | */ 21 | /* Width Scale */ 22 | .w-66 { width: 66%; } 23 | 24 | @media (--breakpoint-not-small) { 25 | .w-66-ns { width: 66%; } 26 | } 27 | 28 | @media (--breakpoint-medium) { 29 | .w-66-m { width: 66%; } 30 | } 31 | 32 | @media (--breakpoint-large) { 33 | .w-66-l { width: 66%; } 34 | } 35 | 36 | @media print { 37 | .w-33-p { width: 33%; } 38 | 39 | .w-66-p { width: 66%; } 40 | } 41 | -------------------------------------------------------------------------------- /css/main.css: -------------------------------------------------------------------------------- 1 | @charset 'UTF-8'; 2 | 3 | /* nomralize */ 4 | @import 'normalize.css'; 5 | 6 | /* Tachyons */ 7 | @import 'tachyons/src/tachyons.css'; 8 | @import 'tachyons-columns/src/tachyons-columns.css'; 9 | /* Print styles */ 10 | @import 'tachyons-print/src/tachyons-print.css'; 11 | 12 | /* clrs.cc */ 13 | @import 'colors.css/src/colors.css'; 14 | 15 | /* layout */ 16 | @import '_vr-reset.css'; 17 | @import '_page'; 18 | @import '_widths'; 19 | @import '_list'; 20 | @import '_columns'; 21 | -------------------------------------------------------------------------------- /nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "verbose": true, 3 | "ignore": [ 4 | ".git", 5 | "node_modules", 6 | "_build" 7 | ], 8 | "watch": [ 9 | "source/**/*.*", 10 | "css/**/*.*", 11 | "templates/**/*.*" 12 | ], 13 | "env": { 14 | "NODE_ENV": "development" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "metalsmith-resume", 3 | "version": "0.0.6", 4 | "description": "A resume generator, built with Metalsmith", 5 | "main": "build.js", 6 | "engines": { 7 | "node": "5.9.0" 8 | }, 9 | "scripts": { 10 | "start": "npm run browser_sync & NODE_ENV=development nodemon --exec 'npm run test && npm run build && browser-sync reload'", 11 | "browser_sync": "browser-sync start --server _build --no-ui --no-notify", 12 | "build": "node build.js", 13 | "build:minify": "NODE_ENV=production npm run build", 14 | "pdf": "NODE_ENV=print npm run build && npm run build", 15 | "test": "standard && stylelint css/*.css" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "git+https://github.com/lowmess/metalsmith-resume.git" 20 | }, 21 | "keywords": [ 22 | "metalsmith", 23 | "resume", 24 | "cv", 25 | "static", 26 | "site", 27 | "skeleton", 28 | "theme" 29 | ], 30 | "author": "Alec Lomas", 31 | "license": "MIT", 32 | "bugs": { 33 | "url": "https://github.com/lowmess/metalsmith-resume/issues" 34 | }, 35 | "homepage": "https://github.com/lowmess/metalsmith-resume#readme", 36 | "dependencies": { 37 | "autoprefixer": "^6.3.6", 38 | "colors.css": "^3.0.0", 39 | "css-mqpacker": "^5.0.1", 40 | "cssnano": "^3.7.1", 41 | "get-contrast": "^2.0.0", 42 | "html-pdf": "^2.0.1", 43 | "metalsmith": "^2.1.0", 44 | "metalsmith-collections": "^0.7.0", 45 | "metalsmith-default-values": "^1.0.1", 46 | "metalsmith-drafts": "^0.0.1", 47 | "metalsmith-html-minifier": "^2.0.0", 48 | "metalsmith-layouts": "^1.6.5", 49 | "metalsmith-markdownit": "^0.3.0", 50 | "metalsmith-metadata": "0.0.4", 51 | "metalsmith-permalinks": "^0.5.0", 52 | "moment": "^2.13.0", 53 | "normalize.css": "^4.1.1", 54 | "postcss": "^5.0.21", 55 | "postcss-color-function": "^2.0.1", 56 | "postcss-custom-media": "^5.0.1", 57 | "postcss-custom-properties": "^5.0.1", 58 | "postcss-focus": "^1.0.0", 59 | "postcss-import": "^8.1.2", 60 | "postcss-nested": "^1.0.0", 61 | "postcss-uncss": "0.0.1", 62 | "pug": "^2.0.0-alpha8", 63 | "tachyons": "^4.0.4", 64 | "tachyons-columns": "^1.0.0", 65 | "tachyons-print": "^4.0.4", 66 | "uncss": "^0.13.0" 67 | }, 68 | "devDependencies": { 69 | "browser-sync": "^2.12.10", 70 | "cz-conventional-changelog": "^1.2.0", 71 | "nodemon": "^1.9.2", 72 | "standard": "^8.6.0", 73 | "stylelint": "^7.7.1", 74 | "stylelint-config-lowmess": "^0.0.1" 75 | }, 76 | "stylelint": { 77 | "extends": "stylelint-config-lowmess" 78 | }, 79 | "config": { 80 | "commitizen": { 81 | "path": "./node_modules/cz-conventional-changelog" 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowmess/metalsmith-resume/a5bcde3d311bf5503256c82913b895b8e24444c5/preview.png -------------------------------------------------------------------------------- /resume.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowmess/metalsmith-resume/a5bcde3d311bf5503256c82913b895b8e24444c5/resume.pdf -------------------------------------------------------------------------------- /source/404.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 404 3 | permalink: false 4 | --- 5 | -------------------------------------------------------------------------------- /source/education.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Education 3 | layout: collection.pug 4 | --- 5 | -------------------------------------------------------------------------------- /source/education/owen-patterson.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: High School Diploma 3 | subtitle: Owen Patterson H.S. 4 | startDate: 1985-08-11 5 | endDate: 1989-05-31 6 | location: Capitol City, USA 7 | --- 8 | 9 | Excelled in science, math and computer courses. Became a respected member of the school community through involvement in football and hockey. 10 | -------------------------------------------------------------------------------- /source/experience.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Experience 3 | layout: collection.pug 4 | --- 5 | -------------------------------------------------------------------------------- /source/experience/metacortex.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Software Programmer 3 | subtitle: MetaCortex 4 | url: http://matrix.wikia.com/wiki/MetaCortex 5 | startDate: 1996-09-13 6 | endDate: 1999-03-31 7 | location: Capitol City, USA 8 | --- 9 | 10 | Worked as a computer programmer for the MetaCortex software company. Had a social security number. Sold contraband programming and hacks under the alias Neo. 11 | -------------------------------------------------------------------------------- /source/experience/nebuchadnezzar.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: One-in-Training 3 | subtitle: Nebuchadnezzar 4 | url: http://matrix.wikia.com/wiki/Nebuchadnezzar 5 | startDate: 2198-03-31 6 | endDate: 2199-09-18 7 | location: Reality 8 | --- 9 | 10 | Learned the truth about reality. Gained the ability to bend the rules of the Matrix. Regularly commuted between realities. 11 | -------------------------------------------------------------------------------- /source/experience/zion.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: The One 3 | subtitle: City of Zion 4 | published: true 5 | url: 'http://matrix.wikia.com/wiki/Zion' 6 | startDate: 2199-09-19T00:00:00.000Z 7 | location: 'Zion, Earth' 8 | --- 9 | 10 | Engaged in cutthroat negotiations with The Architect. Secured the freedom of the human race. Squashed a particularly errant program in the Matrix source code. 11 | -------------------------------------------------------------------------------- /source/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Resume 3 | permalink: false 4 | --- 5 | -------------------------------------------------------------------------------- /source/person.yaml: -------------------------------------------------------------------------------- 1 | name: Thomas A. Anderson 2 | # Info to show in header 3 | email: neo@zion.gov 4 | phone: (312) 555-0690 5 | location: Zion, Earth 6 | # Header introduction / mission statement 7 | intro: I carry the Matrix's source code, known as the Prime Program. This gives me the ability to freely manipulate the simulated reality of the Matrix, similar to the authority a system administrator has over a given system. I manifest these abilities as various superhuman powers. 8 | #for Twitter cards: 9 | twitter: '@neo' 10 | # Removing all proficiencies will remove the section from the resume 11 | proficiencies: 12 | # - list item 13 | - Hacking 14 | - Creative entrepeneurship 15 | - Martial arts 16 | - Negotiations 17 | - Hovercraft piloting 18 | # Links to include in header 19 | links: 20 | # text: http://link.com 21 | '@neo': https://github.com/neo 22 | -------------------------------------------------------------------------------- /source/site.yaml: -------------------------------------------------------------------------------- 1 | # SEO / tag information 2 | title: The Resume of Thomas A. Anderson (The One) 3 | description: Prophesized by The Oracle to be The One, Thomas A. Anderson freed humanity from the Matrix and ended the Machine War. 4 | # theme color for header, borders, section headings 5 | # For best results, choose a color that has a color ratio of at least 3.5 6 | # against white. Otherwise, all text etc is set to black to preserve readability 7 | # @link http://leaverou.github.io/contrast-ratio/ 8 | theme: '#0074D9' 9 | # of work experiences to show 10 | jobs: 3 11 | # of educational experiences to show 12 | schools: 1 13 | # show 'References available' link in footer 14 | references: true 15 | # Remove theme color on print 16 | printstyles: true 17 | # Show promo link under resume (you probably want to set this to false) 18 | promolink: true 19 | -------------------------------------------------------------------------------- /templates/collection.pug: -------------------------------------------------------------------------------- 1 | extends default 2 | 3 | block content 4 | 5 | +section-title(title) 6 | if title == 'Experience' 7 | for job in collections.experience 8 | +experience(job) 9 | else if title == 'Education' 10 | for school in collections.education 11 | +experience(school) 12 | 13 | +footer 14 | p: +link('Back to Full Resume', '/') 15 | -------------------------------------------------------------------------------- /templates/components/columns.pug: -------------------------------------------------------------------------------- 1 | //- Left column of two column layout 2 | mixin left-column 3 | .w-33-ns.w-33-p.fl-ns.fl-p.mt1.mb3.mb1-ns.mv1-p 4 | block 5 | 6 | mixin right-column 7 | .w-66-ns.w-66-p.fr-ns.fr-p.mv1.mv1-p 8 | block 9 | -------------------------------------------------------------------------------- /templates/components/experience.pug: -------------------------------------------------------------------------------- 1 | //- Experiences are the molecular unit of the resume. They are what the markdown 2 | files in the source directory compile in to. 3 | mixin experience(exp) 4 | +section 5 | //- Position 6 | h3.f3.mb2.mb0-p.fw6= exp.title 7 | //- Metadata 8 | +left-column 9 | ul.list.ml0.pl0.f5.mt1.fw2 10 | //- Place of Work 11 | li.fw5 12 | if exp.url 13 | +link(exp.subtitle, exp.url) 14 | else 15 | = exp.subtitle 16 | //- Time 17 | li 18 | time(datetime=moment.utc(exp.startDate))= moment.utc(exp.startDate).format("MMM YYYY") 19 | | – 20 | if exp.endDate 21 | time(datetime=moment.utc(exp.endDate))= moment.utc(exp.endDate).format("MMM YYYY") 22 | else 23 | | Present 24 | //- Location 25 | if exp.location 26 | li= exp.location 27 | 28 | //- Contents 29 | if exp.contents 30 | +right-column 31 | .measure.f5 32 | != exp.contents 33 | -------------------------------------------------------------------------------- /templates/components/footer.pug: -------------------------------------------------------------------------------- 1 | //- Footer 2 | mixin footer 3 | footer.mt4 4 | hr.w4.ba.b--accent.bw1.ml0(class=site.printstyles ? 'b--dark-gray-p' : '') 5 | block 6 | -------------------------------------------------------------------------------- /templates/components/links.pug: -------------------------------------------------------------------------------- 1 | //- Links 2 | mixin link(text, url) 3 | a.link.dark-gray.underline-hover(href=url)= text 4 | 5 | mixin accent-link(text, url) 6 | a.link.accent.underline-hover(href=url, class=site.printstyles ? 'dark-gray-p' : '')= text 7 | 8 | mixin header-link(text, url) 9 | a.link.bg-accent-text.underline-hover(href=url, class=site.printstyles ? 'dark-gray-p' : '')= text 10 | -------------------------------------------------------------------------------- /templates/components/section.pug: -------------------------------------------------------------------------------- 1 | //- Section elements 2 | mixin section-title(content) 3 | h3.f5.fw7.mt2.mb3.ttu.accent(class=site.printstyles ? 'dark-gray-p' : '') 4 | if block 5 | block 6 | else 7 | = content 8 | 9 | mixin section 10 | section.cf.mb4.mb3-ns.mb3-p 11 | block 12 | -------------------------------------------------------------------------------- /templates/default.pug: -------------------------------------------------------------------------------- 1 | doctype html 2 | include components/links 3 | include components/columns 4 | include components/section 5 | include components/footer 6 | include components/experience 7 | 8 | head 9 | include partials/head 10 | 11 | body.bg-white.bg-light-gray-page.bg-white-p.dark-gray(class= process.env.NODE_ENV == 'print' ? 'helvetica' : 'sans-serif') 12 | article.mw-page.mv-5-page.center.ma0-p.shadow-2-page.lh-title 13 | include partials/header 14 | 15 | main.pa4.bg-white 16 | block content 17 | 18 | if site.jobs > 0 19 | +section-title 20 | +accent-link('Experience', '/experience') 21 | +section 22 | - for (var i = 0; i < site.jobs; i++) 23 | - if (collections.experience[i]) 24 | +experience(collections.experience[i]) 25 | 26 | if site.schools > 0 27 | +section-title 28 | +accent-link('Education', '/education') 29 | +section 30 | - for (var i = 0; i < site.schools; i++) 31 | - if (collections.education[i]) 32 | +experience(collections.education[i]) 33 | 34 | if person.proficiencies 35 | +section 36 | +left-column 37 | +section-title('Proficiencies') 38 | +right-column 39 | ul.cc2-ns.cg3-ns.cc2-p.cg3-p.pl0.mt3.mt0-ns.mt0-p.list-inside-ns.list-inside-p 40 | each skill in person.proficiencies 41 | li= skill 42 | 43 | if person.email && site.references 44 | +footer 45 | p: +link('References available upon request', 'mailto:' + person.email) 46 | 47 | if site.promolink 48 | footer.pb4.tc.dn.dn-p.db-page 49 | p Made with #[+accent-link('Metalsmith Resume', 'https://github.com/lowmess/metalsmith-resume')] by #[+accent-link('@lowmess', 'https://github.com/lowmess/')] 50 | -------------------------------------------------------------------------------- /templates/partials/head.pug: -------------------------------------------------------------------------------- 1 | meta(charset="UTF-8") 2 | meta(content="width=device-width, initial-scale=1", name="viewport") 3 | meta(http-equiv="X-UA-Compatible", content="IE=edge") 4 | meta(name="theme-color", content=site.theme) 5 | 6 | meta(name="description", content=site.description) 7 | 8 | //- Open Graph / Twitter Card 9 | if person.twitter 10 | meta(name="twitter:site", content=person.twitter) 11 | meta(name="twitter:card", content="summary") 12 | meta(property="og:title", name="twitter:title", content=site.title) 13 | meta(property="og:url", content=path) 14 | meta(property="og:description", name="twitter:description", content=site.description) 15 | 16 | title= site.title 17 | 18 | //- Create theme color classes: 19 | - 20 | function getTextColor () { 21 | var darkgray = '#333333' 22 | var white = '#ffffff' 23 | 24 | if (contrast.ratio(site.theme, white) >= 3.5) { 25 | return white 26 | } else { 27 | return darkgray 28 | } 29 | } 30 | 31 | function getAccentColor () { 32 | var darkgray = '#333333' 33 | var white = '#ffffff' 34 | 35 | if (contrast.ratio(site.theme, white) >= 3.5) { 36 | return site.theme 37 | } else { 38 | return darkgray 39 | } 40 | } 41 | 42 | style. 43 | .bg-accent { background-color: #{site.theme}; } 44 | .bg-accent-text { color: #{getTextColor()}; } 45 | .accent { color: #{getAccentColor()}; } 46 | .b--accent { border-color: #{site.theme}; } 47 | ::selection { 48 | background-color: #{site.theme}; 49 | color: #{getTextColor()}; 50 | } 51 | 52 | if process.env.NODE_ENV == 'print' 53 | style. 54 | html { font-size: 75%; } 55 | 56 | link(rel="stylesheet", type="text/css", href="/css/main.css") 57 | -------------------------------------------------------------------------------- /templates/partials/header.pug: -------------------------------------------------------------------------------- 1 | header.pa4.bg-accent.bg-accent-text(class=site.printstyles ? 'dark-gray-p bg-white-p pb0-p' : '') 2 | h1.f2.f1-ns.mb1: a.link.bg-accent-text(href="/", class=site.printstyles ? 'dark-gray-p' : '')!= person.name 3 | .cf 4 | +left-column 5 | ul.list.ml0.pl0.mb2.mb0-ns.f5 6 | if person.email 7 | li: +header-link(person.email, 'mailto:' + person.email) 8 | if person.phone 9 | li= person.phone 10 | if person.location 11 | li= person.location 12 | if person.links 13 | each value, index in person.links 14 | li: +header-link(index, value) 15 | +right-column 16 | if person.intro 17 | p.measure.mt0.f5!= person.intro 18 | --------------------------------------------------------------------------------