├── .gitignore ├── public └── pug.png ├── developers-detail ├── index.js ├── model.js ├── controller.js └── view.pug ├── developers-landing ├── index.js ├── sort-button │ ├── index.pug │ ├── view.pug │ └── component.js ├── developer-tile │ ├── index.pug │ ├── component.js │ └── view.pug ├── model.js ├── controller.js ├── store.js ├── view.pug └── app.js ├── package.json ├── index.js ├── helpers ├── developers.js └── developers.json ├── README.md └── index.pug /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /public/pug.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryan-haskell/one-north-demo/HEAD/public/pug.png -------------------------------------------------------------------------------- /developers-detail/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 3 | controller: require('./controller') 4 | 5 | }; 6 | -------------------------------------------------------------------------------- /developers-landing/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 3 | controller: require('./controller') 4 | 5 | }; 6 | -------------------------------------------------------------------------------- /developers-landing/sort-button/index.pug: -------------------------------------------------------------------------------- 1 | script(type="text/x-template" id="sortButtonTemplate") 2 | include view.pug 3 | 4 | script(type="text/javascript") 5 | include component.js 6 | -------------------------------------------------------------------------------- /developers-landing/sort-button/view.pug: -------------------------------------------------------------------------------- 1 | a.button.is-medium(v-on:click="sortBy()" style="flex:1;") 2 | span(v-html="label") 3 | span.icon 4 | i(v-bind:class="iconClasses") 5 | -------------------------------------------------------------------------------- /developers-landing/developer-tile/index.pug: -------------------------------------------------------------------------------- 1 | script(type="text/x-template" id="developerTileTemplate") 2 | include view.pug 3 | 4 | script(type="text/javascript") 5 | include component.js 6 | -------------------------------------------------------------------------------- /developers-landing/developer-tile/component.js: -------------------------------------------------------------------------------- 1 | Vue.component('developerTile', { 2 | 3 | template: '#developerTileTemplate', 4 | 5 | props: ['developer'], 6 | 7 | computed: { 8 | 9 | fullName: function() { 10 | return this.developer.firstName + ' ' + this.developer.lastName; 11 | } 12 | 13 | } 14 | 15 | }); 16 | -------------------------------------------------------------------------------- /developers-detail/model.js: -------------------------------------------------------------------------------- 1 | module.exports = function(content, data, app) { 2 | 3 | app = (app != undefined) ? app : {}; 4 | 5 | app.production = (process.env.NODE_ENV === 'PRODUCTION'); 6 | 7 | return { 8 | content: content || { 9 | developer: '', 10 | }, 11 | data: JSON.stringify(data || { 12 | developers: [], 13 | filterQuery: '' 14 | }), 15 | app: app 16 | }; 17 | 18 | }; 19 | -------------------------------------------------------------------------------- /developers-landing/developer-tile/view.pug: -------------------------------------------------------------------------------- 1 | a.box( v-bind:href='"/developers/" + developer.id' ) 2 | article.media 3 | figure.media-left 4 | p.image.is-128x128.is-hidden-mobile 5 | img(v-bind:src='developer.image') 6 | p.image.is-64x64.is-hidden-tablet 7 | img(v-bind:src='developer.image') 8 | .media-content 9 | .content 10 | h2(v-html="fullName") 11 | p(v-html="developer.title") 12 | -------------------------------------------------------------------------------- /developers-landing/model.js: -------------------------------------------------------------------------------- 1 | module.exports = function(content, data, app) { 2 | 3 | app = (app != undefined) ? app : {}; 4 | 5 | app.production = (process.env.NODE_ENV === 'PRODUCTION'); 6 | 7 | return { 8 | content: content || { 9 | title: '', 10 | subtitle: '', 11 | filterPlaceholder: '' 12 | }, 13 | data: JSON.stringify(data || { 14 | developers: [], 15 | filterQuery: '' 16 | }), 17 | app: app 18 | }; 19 | 20 | }; 21 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "one-north-demo", 3 | "version": "1.0.0", 4 | "description": "Demo MVC/MVU hybrid approach", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node index.js", 8 | "dev": "node node_modules/nodemon/bin/nodemon.js index.js", 9 | "test": "echo \"Error: no test specified\" && exit 1" 10 | }, 11 | "author": "Ryan Haskell-Glatz", 12 | "license": "ISC", 13 | "dependencies": { 14 | "express": "^4.14.0", 15 | "pug": "^2.0.0-beta6" 16 | }, 17 | "devDependencies": { 18 | "nodemon": "^1.11.0" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var express = require('express'), 2 | app = express(), 3 | pug = require('pug'); 4 | 5 | var developersLanding = require('./developers-landing'), 6 | developersDetail = require('./developers-detail'); 7 | 8 | app.set('views', '.'); 9 | app.set('view engine', 'pug'); 10 | 11 | app.use(express.static('public')); 12 | 13 | app.get('/', function(req, res) { 14 | 15 | res.redirect('/developers'); 16 | 17 | }); 18 | 19 | app.get('/developers', developersLanding.controller); 20 | 21 | app.get('/developers/:developerId', developersDetail.controller); 22 | 23 | app.listen(3000, function() { 24 | 25 | console.log('Web app ready at port 3000!'); 26 | 27 | }) 28 | -------------------------------------------------------------------------------- /developers-detail/controller.js: -------------------------------------------------------------------------------- 1 | var developersHelper = require('../helpers/developers'); 2 | var model = require('./model'); 3 | 4 | module.exports = function(req, res) { 5 | 6 | var developerId = req.params.developerId; 7 | 8 | developersHelper.getDeveloperById(developerId) 9 | .then(function(developer) { 10 | 11 | var content = { 12 | developer: developer 13 | }; 14 | 15 | var data = {}; 16 | 17 | var app = { 18 | title: 'One North | ' + (developer.firstName + 19 | ' ' + developer.lastName) 20 | }; 21 | 22 | res.render('developers-detail/view', 23 | model(content, data, app)); 24 | 25 | }); 26 | 27 | }; 28 | -------------------------------------------------------------------------------- /developers-landing/controller.js: -------------------------------------------------------------------------------- 1 | var developersHelper = require('../helpers/developers'); 2 | var model = require('./model'); 3 | 4 | module.exports = function(req, res) { 5 | 6 | developersHelper.getAllDevelopers().then(function(developers) { 7 | 8 | var content = { 9 | title: 'Developers', 10 | subtitle: 'Look at these nerds.', 11 | filterPlaceholder: 'Find a developer' 12 | }; 13 | 14 | var data = { 15 | developers: developers, 16 | filterQuery: (req.query.search) ? req.query.search : '' 17 | }; 18 | 19 | var app = { 20 | title: 'One North | Developers' 21 | }; 22 | 23 | res.render('developers-landing/view', 24 | model(content, data, app)); 25 | 26 | }) 27 | 28 | }; 29 | -------------------------------------------------------------------------------- /developers-landing/sort-button/component.js: -------------------------------------------------------------------------------- 1 | Vue.component('sortButton', { 2 | 3 | template: '#sortButtonTemplate', 4 | 5 | props: ['label', 'value'], 6 | 7 | computed: { 8 | 9 | sortOptions: function() { 10 | 11 | return this.$store.state.sortOptions; 12 | 13 | }, 14 | 15 | iconClasses: function() { 16 | 17 | if (this.sortOptions.value == this.value) { 18 | return (this.sortOptions.ascending) ? 19 | 'fa fa-sort-alpha-asc' : 20 | 'fa fa-sort-alpha-desc' 21 | } else { 22 | return ''; 23 | } 24 | 25 | } 26 | 27 | }, 28 | 29 | methods: { 30 | 31 | sortBy: function() { 32 | 33 | this.$store.dispatch('updateSort', this.value); 34 | 35 | } 36 | 37 | } 38 | 39 | }); 40 | -------------------------------------------------------------------------------- /helpers/developers.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | 3 | module.exports = { 4 | 5 | getDeveloperById: function(id) { 6 | 7 | return this.getAllDevelopers().then(function(developers) { 8 | 9 | var developersWithId = 10 | developers.filter(function(developer) { 11 | 12 | return (developer.id === id); 13 | 14 | }); 15 | 16 | var developer = developersWithId[0]; 17 | 18 | if (developer === undefined) { 19 | 20 | return {}; 21 | 22 | } else { 23 | 24 | return developer; 25 | 26 | } 27 | 28 | }); 29 | 30 | }, 31 | 32 | getAllDevelopers: function() { 33 | 34 | return Promise.resolve( 35 | 36 | JSON.parse(fs.readFileSync("helpers/developers.json")) 37 | 38 | ); 39 | 40 | } 41 | 42 | }; 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # One North Demo 2 | > A hybrid approach for modern web applications 3 | 4 | ### Local Development 5 | 1. __`npm install`__ - installs dependencies 6 | 1. __`npm run dev`__ - runs server, watches for file changes 7 | 8 | ### How does he do it? 9 | 10 | I've uploaded a series of _embarrassingly_ lengthy videos to walk you through the __entire__ design process. 11 | 12 | __Video Links:__ 13 | 14 | 1. [MVC with NodeJS](https://www.youtube.com/watch?v=YbKQQkbPE9A&index=1&list=PLuGpJqnV9DXpOLsqS00-dvRJp_iNklQ4R) 15 | 1. [Rendering Views with Pug](https://www.youtube.com/watch?v=EqQj-aYS3nE&index=2&list=PLuGpJqnV9DXpOLsqS00-dvRJp_iNklQ4R&t=535s) 16 | 1. [Advanced Features with VueJS](https://www.youtube.com/watch?v=ZbNuZMAWo-g&index=3&list=PLuGpJqnV9DXpOLsqS00-dvRJp_iNklQ4R&t=2777s) 17 | 1. [Managing State with Vuex](https://www.youtube.com/watch?v=zSd462Dq9Vk&index=4&list=PLuGpJqnV9DXpOLsqS00-dvRJp_iNklQ4R) 18 | -------------------------------------------------------------------------------- /developers-detail/view.pug: -------------------------------------------------------------------------------- 1 | extends ../index.pug 2 | 3 | block content 4 | 5 | 6 | section.hero.is-dark.is-bold.is-medium 7 | .hero-body 8 | .container 9 | h1.title.is-1= content.developer.firstName + " " + content.developer.lastName 10 | h2.subtitle.is-3= content.developer.title 11 | 12 | section.hero 13 | .hero-body 14 | .container 15 | h3.subtitle.is-3 16 | strong= "About " + content.developer.firstName 17 | h3.subtitle.is-4!= content.developer.bio 18 | ul.subtitle.is-4 19 | each fact in content.developer.facts 20 | br 21 | li!= fact 22 | hr 23 | 24 | 25 | a.button.is-large.is-dark.is-expanded.is-outlined(href="/developers") 26 | i.fa.fa-arrow-left(style={"padding-right": "10px"}) 27 | span= "Developers" 28 | -------------------------------------------------------------------------------- /index.pug: -------------------------------------------------------------------------------- 1 | html 2 | head 3 | if app.title 4 | title= app.title 5 | else 6 | title= 'One North' 7 | 8 | link(rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/bulma/0.3.0/css/bulma.min.css') 9 | link(rel='stylesheet' href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css") 10 | meta(name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no") 11 | link(rel="icon" href="/pug.png") 12 | 13 | block head 14 | 15 | body 16 | 17 | #app 18 | block content 19 | 20 | if app.production 21 | script(src="https://cdnjs.cloudflare.com/ajax/libs/vuex/2.1.1/vuex.min.js") 22 | script(src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.8/vue.min.js") 23 | else 24 | script(src="https://cdnjs.cloudflare.com/ajax/libs/vuex/2.1.1/vuex.js") 25 | script(src="https://unpkg.com/vue/dist/vue.js") 26 | 27 | block scripts 28 | -------------------------------------------------------------------------------- /developers-landing/store.js: -------------------------------------------------------------------------------- 1 | Vue.use(Vuex); 2 | 3 | var store = new Vuex.Store({ 4 | 5 | state: { 6 | 7 | developers: pugData.developers, 8 | 9 | filterQuery: pugData.filterQuery, 10 | 11 | sortOptions: { 12 | value: 'firstName', 13 | ascending: true 14 | } 15 | 16 | }, 17 | 18 | mutations: { 19 | 20 | setFilterQuery: function(state, newFilterQuery) { 21 | 22 | state.filterQuery = newFilterQuery; 23 | 24 | }, 25 | 26 | setSortOptionsValue: function(state, sortValue) { 27 | 28 | if (state.sortOptions.value == sortValue) { 29 | state.sortOptions.ascending = !state.sortOptions.ascending; 30 | } else { 31 | state.sortOptions = { 32 | value: sortValue, 33 | ascending: true 34 | } 35 | } 36 | 37 | } 38 | 39 | }, 40 | 41 | actions: { 42 | 43 | updateFilterQuery: function(context, newFilterQuery) { 44 | 45 | context.commit("setFilterQuery", newFilterQuery); 46 | 47 | }, 48 | 49 | updateSort: function(context, sortValue) { 50 | 51 | context.commit('setSortOptionsValue', sortValue); 52 | 53 | } 54 | 55 | } 56 | 57 | }); 58 | -------------------------------------------------------------------------------- /developers-landing/view.pug: -------------------------------------------------------------------------------- 1 | extends ../index.pug 2 | 3 | 4 | block content 5 | 6 | section.hero.is-dark.is-bold.is-medium 7 | .hero-body 8 | .container 9 | h1.title.is-1= content.title 10 | h2.subtitle.is-3= content.subtitle 11 | 12 | .container(style={"padding": "20px"}) 13 | p.control.has-icon.has-icon-right 14 | input.input.is-large( 15 | type="text" 16 | placeholder= content.filterPlaceholder 17 | v-bind:value="filterQuery" 18 | v-on:input="onFilterQueryInput($event.target.value)" 19 | ) 20 | span.icon.is-medium 21 | i.fa.fa-search 22 | 23 | p.control.has-addons(style={'overflow': 'auto', 'padding': '1px'}) 24 | sort-button( label="First Name" value="firstName" ) 25 | sort-button( label="Last Name" value="lastName" ) 26 | sort-button( label="Title" value="title" ) 27 | 28 | hr 29 | 30 | ul 31 | developer-tile( v-for="dev in displayedDevelopers" 32 | v-bind:developer="dev" ) 33 | 34 | 35 | block scripts 36 | 37 | // Server-rendered data 38 | script(type="text/javascript"). 39 | var pugData = !{data}; 40 | 41 | // Vuex Store 42 | script(text="text/javascript") 43 | include store.js 44 | 45 | // Vue Components 46 | include developer-tile/index.pug 47 | include sort-button/index.pug 48 | 49 | // Vue App 50 | script(text="text/javascript") 51 | include app.js 52 | -------------------------------------------------------------------------------- /developers-landing/app.js: -------------------------------------------------------------------------------- 1 | var vm = new Vue({ 2 | 3 | el: '#app', 4 | 5 | store: store, 6 | 7 | computed: { 8 | 9 | developers: function() { 10 | 11 | return this.$store.state.developers; 12 | 13 | }, 14 | 15 | filterQuery: function() { 16 | 17 | return this.$store.state.filterQuery; 18 | 19 | }, 20 | 21 | sortOptions: function() { 22 | 23 | return this.$store.state.sortOptions; 24 | 25 | }, 26 | 27 | displayedDevelopers: function() { 28 | 29 | var developers = this.developers; 30 | 31 | var filteredDevelopers = 32 | developers.filter(this.filterDevelopers); 33 | 34 | var filteredAndSortedDevelopers = 35 | filteredDevelopers.sort(this.sortDevelopers); 36 | 37 | return filteredAndSortedDevelopers; 38 | 39 | } 40 | 41 | }, 42 | 43 | methods: { 44 | 45 | filterDevelopers: function(developer) { 46 | 47 | var lowercaseName = this.getFullName(developer).toLowerCase(); 48 | var lowercaseQuery = this.filterQuery.toLowerCase(); 49 | 50 | return lowercaseName.indexOf(lowercaseQuery) > -1; 51 | 52 | }, 53 | 54 | sortDevelopers: function(a, b) { 55 | 56 | var LT = -1, 57 | GT = 1, 58 | EQ = 0; 59 | var value = this.sortOptions.value, 60 | ascending = this.sortOptions.ascending; 61 | 62 | var aVal = a[value]; 63 | var bVal = b[value]; 64 | 65 | if (aVal < bVal) 66 | return (ascending) ? LT : GT; 67 | else if (aVal > bVal) 68 | return (ascending) ? GT : LT; 69 | else 70 | return EQ; 71 | 72 | }, 73 | 74 | onFilterQueryInput: function(filterQuery) { 75 | 76 | this.updateUrl(filterQuery); 77 | 78 | this.$store.dispatch('updateFilterQuery', filterQuery); 79 | 80 | }, 81 | 82 | updateUrl: function(value) { 83 | 84 | if (value.length == 0) { 85 | 86 | window.history.replaceState({}, 'Developers', 87 | '/developers'); 88 | 89 | } else { 90 | 91 | window.history.replaceState({}, 'Developers', 92 | '/developers?search=' + value); 93 | 94 | } 95 | 96 | }, 97 | 98 | getFullName: function(developer) { 99 | 100 | return developer.firstName + ' ' + developer.lastName; 101 | 102 | } 103 | 104 | }, 105 | 106 | created: function() { 107 | console.log('Received ' + this.developers.length + 108 | ' developers.'); 109 | } 110 | 111 | }); 112 | -------------------------------------------------------------------------------- /helpers/developers.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "id": "pete-amundson", 3 | "title": "Technical Strategist", 4 | "image": "http://onenorth.blob.core.windows.net/keystone/Pete-Amundson_BW2.png", 5 | "bio": "As a Technical Strategist at One North, Pete serves as a key technical contact throughout all his client engagements. He considers the technical needs of his clients alongside the broader scope of a company’s brand, marketing and general business needs. His close attention to the ever-changing technology landscape helps clients stay on top of their audiences’ evolving information consumption habits.", 6 | "facts": [ 7 | "Favorite color:  #cd1922 ", 8 | "What you wanted to be when you were little: An astronaut" 9 | ], 10 | "firstName": "Pete", 11 | "lastName": "Amundson" 12 | }, { 13 | "id": "emma-birdsong", 14 | "title": "Associate Developer", 15 | "image": "http://onenorth.blob.core.windows.net/keystone/emma2.png", 16 | "bio": "As an Associate Developer, Emma will use her build-up of knowledge to create and improve solutions for clients through the implementation of web technologies.  Her knowledge of front-end design and nodejs gives Emma a unique perspective and the opportunity to contribute to her team throughout a project timeline. ", 17 | "facts": [ 18 | "Favorite movie: Fight Club, The Royal Tenenbaums, and Bring It On", 19 | "Most unusual job: In high school, I was the “popcorn girl” at a local bank. I literally just made popcorn and gave it to customers every Friday afternoon." 20 | ], 21 | "firstName": "Emma", 22 | "lastName": "Birdsong" 23 | }, { 24 | "id": "michael-blaha", 25 | "title": "Architect", 26 | "image": "http://onenorth.blob.core.windows.net/keystone/Michael-Blaha_BW.jpg", 27 | "bio": "Michael Blaha is an Architect  at One North, bringing his skills in both front and back-end development to craft extraordinary digital experiences for our clients. In his free time, he enjoys making video games and has designed, coded and released two games on the Windows Phone platform.", 28 | "facts": [ 29 | "Favorite movie: Big Trouble in Little China", 30 | "Favorite Chicago spot: Soldier Field" 31 | ], 32 | "firstName": "Michael", 33 | "lastName": "Blaha" 34 | }, { 35 | "id": "keegan-bowers", 36 | "title": "Developer", 37 | "image": "http://onenorth.blob.core.windows.net/keystone/Keegan-Bowers_BW.jpg", 38 | "bio": "As a Developer at One North, Keegan works to build digital properties for our clients. With over six years in cross-platform web development, Keegan enjoys working with his team to produce quality materials that meet and exceed client expectations. Keegan has a Bachelor's of Science in Computer Science from Heriot-Watt University in Edinburgh, Scotland.", 39 | "facts": [ 40 | "Three hobbies: Car enthusiast, self-taught mechanic, amateur astronomer", 41 | "One more hobby: Noob home beer brewer (I have too many hobbies.)" 42 | ], 43 | "firstName": "Keegan", 44 | "lastName": "Bowers" 45 | }, { 46 | "id": "erik-carron", 47 | "title": "Developer", 48 | "image": "http://onenorth.blob.core.windows.net/keystone/Erik-Carron_BW_Cropped.jpg", 49 | "bio": "As a Developer at One North, Erik provides technical assistance to new and ongoing client projects. He brings his wide range of technical expertise and experience to his role at One North. Erik graduated from Purdue University with a degree in Computer Engineering.", 50 | "facts": [ 51 | "Fun fact: My first name is John, however, I go by my middle name Erik.", 52 | "Coach Erik: I coach the boys lacrosse team at Downers Grove South High School." 53 | ], 54 | "firstName": "Erik", 55 | "lastName": "Carron" 56 | }, { 57 | "id": "michael-ciacco", 58 | "title": "Systems Engineer", 59 | "image": "http://onenorth.blob.core.windows.net/keystone/Michael-Ciacco_BW-Cropped.jpg", 60 | "bio": "As a Systems Engineer at One North, Michael's responsibilities include the configuration, maintenance and 24/7 support of our clients' digital experiences. He understands the importance of maintaining business-critical applications, and ensures that they are up and running at all times.", 61 | "facts": [ 62 | "Extracurricular activity: Riding my vintage late 70's red Roland bicycle around the city", 63 | "Favorite dessert: Gelato" 64 | ], 65 | "firstName": "Michael", 66 | "lastName": "Ciacco" 67 | }, { 68 | "id": "ethel-crosby", 69 | "title": "Head of Technology Operations", 70 | "image": "http://onenorth.blob.core.windows.net/keystone/Ethel-Crosby_BW.jpg", 71 | "bio": "As Head of Technology Operations at One North Interactive, Ethel is responsible for the management and execution of leading digital technology solutions and software product management for B2B relationship-based businesses. Never one to shy away from a challenge, Ethel once zip-lined, upside down, in a rain forest in Costa Rica.", 72 | "facts": [ 73 | "Favorite movie quote: \"With great power comes great responsibility.\" - Spiderman", 74 | "Favorite vending machine snack: Reeses Pieces" 75 | ], 76 | "firstName": "Ethel", 77 | "lastName": "Crosby" 78 | }, { 79 | "id": "chris-elston", 80 | "title": "Technical Lead", 81 | "image": "http://onenorth.blob.core.windows.net/keystone/blank_man (1).jpg", 82 | "bio": "As Technical Lead, Chris uses his digital expertise to offer smart solutions as well as mentor his team. Chris has worked with numerous platforms, languages and systems that give him a unique perspective to build innovative sites for clients.", 83 | "facts": [ 84 | "Fun fact: I spent a semester in Bonn, Germany back in college.", 85 | "Favorite hobby: I’ve been brewing my own beer, off and on, since 2000" 86 | ], 87 | "firstName": "Chris", 88 | "lastName": "Elston" 89 | }, { 90 | "id": "eric-frus", 91 | "title": "Managing Architect", 92 | "image": "http://onenorth.blob.core.windows.net/keystone/Eric-Frus.jpg", 93 | "bio": "Eric Frus is a Managing Architect at One North, leading a team of developers and working on the architecture of web applications and custom data integration solutions. He prides himself in having the cleanest desk in the office (a prize he awarded to himself).", 94 | "facts": ["Favorite movie: Office Space", 95 | "Favorite Chicago spot: 1 N Dearborn Street, Suite 650" 96 | ], 97 | "firstName": "Eric", 98 | "lastName": "Frus" 99 | }, { 100 | "id": "ryan-haskell-glatz", 101 | "title": "Associate Developer", 102 | "image": "http://onenorth.blob.core.windows.net/keystone/ryan2.png", 103 | "bio": "As an Associate Developer, Ryan is responsible for the implementation of specified features designed with his team.  Through collaboration, he helps provide efficient and effective solutions through skillful technology implementation practices.", 104 | "facts": [ 105 | "Favorite movie quote: “You keep using that word… I do not think it means what you think it means.” – Inigo Montoya, Princess Bride", 106 | "Favorite Chicago spot: Millennium Park" 107 | ], 108 | "firstName": "Ryan", 109 | "lastName": "Haskell-Glatz" 110 | }, { 111 | "id": "alex-hawley", 112 | "title": "Technical Lead", 113 | "image": "http://onenorth.blob.core.windows.net/keystone/Alex_Hawley.jpg", 114 | "bio": "As Technical Lead, Alex leads the planning, implementation and deployment of custom web solutions across multiple platforms.  He is certified in both Sitecore and Sitefinity content management systems, and works with clients to establish goals for their desired applications, building robust implementations to meet those goals.", 115 | "facts": [ 116 | "Favorite hobby: Running. I’ve ran over 23 marathons which included running 12 in 2013.", 117 | "Favorite travel experience: Taking a trip out to the west coast to run along Highway 1 on the Pacific Ocean. If you don’t want to run on Highway 1, I would strongly recommend at least driving down the coast." 118 | ], 119 | "firstName": "Alex", 120 | "lastName": "Hawley" 121 | }, { 122 | "id": "rene-hernandez", 123 | "title": "Senior Front-End Developer", 124 | "image": "http://onenorth.blob.core.windows.net/keystone/Rene-Hernandez.jpg", 125 | "bio": "Rene is a Senior Front-End Developer at One North, ensuring client satisfaction through visually appealing web pages and digital design. An avid tomato-lover, Rene enjoys taking care of his tomato plant when he isn’t coding away amongst his fellow FEDs.", 126 | "facts": [ 127 | "Favorite movie quote: \"Get to the choppa!\" - Arnold Schwarzenegger, Predator", 128 | "Favorite breakfast food: Vegetable skillet with eggs over-easy (the hashbrowns can make or break this dish).
" 129 | ], 130 | "firstName": "Rene", 131 | "lastName": "Hernandez" 132 | }, { 133 | "id": "ryan-horner", 134 | "title": "Managing Director, Technology", 135 | "image": "http://onenorth.blob.core.windows.net/keystone/ryan-horner.jpg", 136 | "bio": "As Managing Director of Technology, Ryan is responsible for overseeing One North’s strategy related to technical applications, systems and client implementations. He got his start at age seven, programming an Apple IIe.", 137 | "facts": [ 138 | "Last thing you geeked-out about: This happens on a daily basis, oftentimes to the internet of things coming to life and novel uses of the technology-enabled sharing economy – or some combination of the two.", 139 | "Most unusual job: I grew up on a working farm, so I've had lots of unusual jobs: baling straw, sweeping bins, cleaning a cattle barn, etc. " 140 | ], 141 | "firstName": "Ryan", 142 | "lastName": "Horner" 143 | }, { 144 | "id": "yesuah-iniguez", 145 | "title": "Developer", 146 | "image": "http://onenorth.blob.core.windows.net/keystone/blank_man (1).jpg", 147 | "bio": "As a Developer, Yesuah is responsible for the continued maintenance and development of client websites. With a diverse background in design, development and server experience, he works closely with his team to assure that projects run smoothly.  ", 148 | "facts": [ 149 | "Favorite movie: Shutter (Not the American re-make)", 150 | "Super power you wish you had: The ability to heal like wolverine. My body does not like sports, and MRIs are expensive." 151 | ], 152 | "firstName": "Yesuah", 153 | "lastName": "Iniguez" 154 | }, { 155 | "id": "craig-jacobs", 156 | "title": "Developer", 157 | "image": "http://onenorth.blob.core.windows.net/keystone/Craig-Jacobs_BW.jpg", 158 | "bio": "As a Developer at One North, Craig provides ongoing support and knowledge to assist our clients in achieving their business goals. Solving problems and anticipating client needs, he is able to guide our clients towards lasting technological solutions with advanced and innovative technologies.", 159 | "facts": [ 160 | "Favorite breakfast food: I don’t eat breakfast, but I am a huge proponent of eating multiple lunches.", 161 | "What you wanted to be when you were little: A superhero" 162 | ], 163 | "firstName": "Craig", 164 | "lastName": "Jacobs" 165 | }, { 166 | "id": "vinu-krishnaswamy", 167 | "title": "Architect", 168 | "image": "http://onenorth.blob.core.windows.net/keystone/Vinu-Krishnaswamy_BW.jpg", 169 | "bio": "Vinu is an Architect at One North, responsible for overseeing multiple development projects and architecting and implementing full life cycle digital strategies. Fun fact: he can speak three languages fluently and two more in a way that irritates native speakers.", 170 | "facts": ["Favorite season: Summer – love the beach.", 171 | "Super power: Ability to breathe underwater" 172 | ], 173 | "firstName": "Vinu", 174 | "lastName": "Krishnaswamy" 175 | }, { 176 | "id": "tom-mahr", 177 | "title": "Senior Developer", 178 | "image": "http://onenorth.blob.core.windows.net/keystone/Tom-Mahr_BW.jpg", 179 | "bio": "As a Developer at One North, Tom builds and maintains websites and applications for our clients. By collaborating with his team, he is able to provide best possible solutions with efficient and well-practiced implementation capabilities.", 180 | "facts": ["Favorite movie: Royal Tenenbaums", 181 | "Favorite breakfast food: Eggs Benedict (with Homemade Hollandaise Sauce, not the powder mixed stuff)" 182 | ], 183 | "firstName": "Tom", 184 | "lastName": "Mahr" 185 | }, { 186 | "id": "kyle-marek", 187 | "title": "Developer", 188 | "image": "http://onenorth.blob.core.windows.net/keystone/Kyle_Marek.jpg", 189 | "bio": "Kyle brings years of experience working with .NET and web-associated technologies to his role as a Developer at One North. Constantly striving to achieve his clients’ needs and goals, Kyle uses various front-end and back-end technologies.", 190 | "facts": [ 191 | "Fun fact: In my spare time, I like going to concerts and collect vinyl. I have collected over 100 records in the past year alone.", 192 | "What you wanted to be when you were little: Ninja astronaut" 193 | ], 194 | "firstName": "Kyle", 195 | "lastName": "Marek" 196 | }, { 197 | "id": "kyle-mattimore", 198 | "title": "Developer", 199 | "image": "http://onenorth.blob.core.windows.net/keystone/Kyle-Mattimore_BW_Cropped.jpg", 200 | "bio": "As a Developer at One North, Kyle \"solves problems and builds cool things.\" He received his Computer Science degree from the University of Michigan and considers himself a self-taught network/security geek.", 201 | "facts": [ 202 | "Fun fact: I have a hobbyist recording studio and play around with making music. Some evidence of this can be seen here.", 203 | "Favorite sport to play: I will go to any lengths for a good game of Ultimate Frisbee." 204 | ], 205 | "firstName": "Kyle", 206 | "lastName": "Mattimore" 207 | }, { 208 | "id": "adam-moericke", 209 | "title": "Senior Systems Engineer", 210 | "image": "http://onenorth.blob.core.windows.net/keystone/Adam-Moericke.jpg", 211 | "bio": "As a Senior Systems Engineer at One North, Adam helps provide a stable and high performing environment for the client websites that One North hosts.", 212 | "facts": [ 213 | "School and major: University of Wisconsin-Madison / Computer Engineering", 214 | "Last thing you geeked out about: Did you know that within the next 30 years, you'll be able to \"ingest\" information by simply taking a pill? You can watch MIT Media Lab Founder Nicholas Negroponte's prediction during this TedTalk" 215 | ], 216 | "firstName": "Adam", 217 | "lastName": "Moericke" 218 | }, { 219 | "id": "alex-morask", 220 | "title": "Associate Developer", 221 | "image": "http://onenorth.blob.core.windows.net/keystone/Alex_Morask.jpg", 222 | "bio": "As an Associate Developer at One North, Alex assists in the process of building out new technological solutions, as well as improving existing applications that help clients better engage with customers and prospects.  He started his career as a marketing consultant, giving him a unique perspective to see problems and solutions from the client’s point-of-view. ", 223 | "facts": [], 224 | "firstName": "Alex", 225 | "lastName": "Morask" 226 | }, { 227 | "id": "manny-nelson", 228 | "title": "Senior Developer", 229 | "image": "http://onenorth.blob.core.windows.net/keystone/Manny-Nelson.jpg", 230 | "bio": "As a Senior Developer at One North, Manny is primarily tasked with building extraordinary digital experiences from initial project assignment to completion. He works to provide advanced technical guidance from years of experience in digital development and maintains user-friendly capabilities for One North and our clients.", 231 | "facts": [ 232 | "Favorite season: Fall - beautiful, great temperatures in the Midwest, football season, Halloween, apple cider, my birthday - all great things.", 233 | "Favorite movie: Big fan of any Christopher Nolan films. And, conversely, I also enjoy most Woody Allen flicks." 234 | ], 235 | "firstName": "Manny", 236 | "lastName": "Nelson" 237 | }, { 238 | "id": "steven-nicholson", 239 | "title": "Developer", 240 | "image": "http://onenorth.blob.core.windows.net/keystone/Steven-Nicholson_BW.jpg", 241 | "bio": "As a Developer at One North, Steven develops and tests code-based solutions for clients. He works with an advanced knowledge of computer programming and understanding of digital systems.", 242 | "facts": ["Favorite season: Fall", 243 | "Favorite breakfast food: Pigs in a Blanket" 244 | ], 245 | "firstName": "Steven", 246 | "lastName": "Nicholson" 247 | }, { 248 | "id": "michael-o'laughlin", 249 | "title": "Head of QA & Managed Applications", 250 | "image": "http://onenorth.blob.core.windows.net/keystone/Michael-OLaughlin_BW.jpg", 251 | "bio": "As Head of QA & Managed Applications, Michael is responsible for delivering One North digital experiences to clients and creating both web applications and custom data integration solutions. Michael’s favorite Chicago spot is at the United Center, watching the Hawks in the playoffs.", 252 | "facts": [ 253 | "Favorite movie quote: “Great moments...are born from great opportunity. And that's what you have here tonight, boys. That's what you've earned here tonight. One game. If we played 'em ten times, they might win nine. But not this game; not tonight.” - Miracle", 254 | "What you wanted to be when you were little: A firefighter" 255 | ], 256 | "firstName": "Michael", 257 | "lastName": "O'Laughlin" 258 | }, { 259 | "id": "zach-peer", 260 | "title": "Director, Client Systems", 261 | "image": "http://onenorth.blob.core.windows.net/keystone/zach-peer.jpg", 262 | "bio": "Zach Peer is the Director of Technology and Client and Internal Systems at One North Interactive. He establishes and maintains the appropriate policies, procedures and controls for One North’s hosted offerings and works to ensure the availability, security and performance of the hosting environment – the hosting environment that he modeled out of Legos (playing with Legos is one of his passions, both with his kids and without).", 263 | "facts": [ 264 | "If I were a vegetable: I'd be a Cucumber because they are cool (and tasty on sandwiches).", 265 | "Last thing you geeked-out about: Backyard Chickens" 266 | ], 267 | "firstName": "Zach", 268 | "lastName": "Peer" 269 | }, { 270 | "id": "alex-pershteyn", 271 | "title": "Architect", 272 | "image": "http://onenorth.blob.core.windows.net/keystone/Alex-Pershteyn.jpg", 273 | "bio": "As an Architect, Alex is responsible for overseeing the implementation, testing and ongoing support of web-based projects. When he’s not coding away on JavaScript, ASP.Net or what-have-you, he is flying off to distant lands, adding to the growing list of countries to which he’s traveled.", 274 | "facts": [ 275 | "What you wanted to be when you were little: A World Traveler", 276 | "Favorite movie: Pulp Fiction" 277 | ], 278 | "firstName": "Alex", 279 | "lastName": "Pershteyn" 280 | }, { 281 | "id": "ben-pomeranz", 282 | "title": "Technical Lead", 283 | "image": "http://onenorth.blob.core.windows.net/keystone/Ben-Pomeranz.jpg", 284 | "bio": "As Technical Lead, Ben builds front-end and behind-the-scenes components for One North's clients and enjoys scanning the technology horizon for new framework opportunities. He is also a comic-book fan, sci-fi geek and goes every year to Comic Con.", 285 | "facts": [ 286 | "What you wanted to be when you were little: Spiderman", 287 | "Super power: Ability to banter well with supervillains" 288 | ], 289 | "firstName": "Ben", 290 | "lastName": "Pomeranz" 291 | }, { 292 | "id": "rob-reilley", 293 | "title": "Senior Developer", 294 | "image": "http://onenorth.blob.core.windows.net/keystone/Rob-Reilley_BW_cropped.jpg", 295 | "bio": "Rob brings over 20 years of experience working in various types of digital environments and technologies to his role as a Senior Developer at One North. He perpetually strives to come up with the best solution for each of his clients’ needs. Rob is a certified Sitecore Developer and received his degree in Computer Information Systems from DeVry University.", 296 | "facts": [ 297 | "Favorite team: I’m a huge Bears fan, and I’ve met many former players while collecting autographs.", 298 | "Favorite hobby: I’m addicted to running. I’ve ran many races anywhere from 1 mile up to a 50k." 299 | ], 300 | "firstName": "Rob", 301 | "lastName": "Reilley" 302 | }, { 303 | "id": "joe-reiser", 304 | "title": "Technical Support Engineer", 305 | "image": "http://onenorth.blob.core.windows.net/keystone/Joe-Reiser_BW_Cropped.jpg", 306 | "bio": "As a Technical Support Engineer at One North, Joe ensures the technology to achieve maximum business effectiveness is efficient, practical and – most importantly – working. He brings over 15 years of personal IT experience to the company as well as more than five years of corporate support in an Enterprise setting.", 307 | "facts": [ 308 | "Hobbies: Amateur astronomy and astrophotography, fishing, trying new restaurants and working out!" 309 | ], 310 | "firstName": "Joe", 311 | "lastName": "Reiser" 312 | }, { 313 | "id": "rikin-shah", 314 | "title": "Technical Lead", 315 | "image": "http://onenorth.blob.core.windows.net/keystone/Rikin-Shah.jpg", 316 | "bio": "As Technical Lead at One North, Rikin brings his passion for coding and technology to debug websites, data integration errors and SEO issues for both One North and our clients. He works with other members of Team Technology to provide the best technical solution that both aligns with client requirements and enables a great user experience.", 317 | "facts": ["Favorite hobby: Gaming and traveling", 318 | "Favorite movie: The Godfather" 319 | ], 320 | "firstName": "Rikin", 321 | "lastName": "Shah" 322 | }, { 323 | "id": "karthik-singh", 324 | "title": "Developer", 325 | "image": "http://onenorth.blob.core.windows.net/keystone/Karthik-Singh_BW.jpg", 326 | "bio": "As a Developer, Karthik is responsible for the continued maintenance as well as new feature additions to current client websites. He also helps resolve client issues with respect to their digital experiences while continually seeking to enhance and upgrade features and applications.", 327 | "facts": [ 328 | "Fun fact: I like to play and produce music in my free time. Currently, that’s been mainly around guitar, but I’m hoping to expand and learn more instruments with time.", 329 | "Education: I graduated from the University of Illinois at Urbana-Champaign with a major in Statistics and a minor in Computer Science. " 330 | ], 331 | "firstName": "Karthik", 332 | "lastName": "Singh" 333 | }, { 334 | "id": "mike-skutta", 335 | "title": "Architect", 336 | "image": "http://onenorth.blob.core.windows.net/keystone/Mike_Skutta.jpg", 337 | "bio": "As an Architect within the Technology Labs group at One North, Mike works to research, test and integrate new technologies for both One North and its clients. He is also a Sitecore Technology MVP and holds more than 14 years of experience architecting, designing, developing software and leading technology teams. Based in Florida, Mike is often seen wheeling around the office via our robot.", 338 | "facts": ["Favorite vending machine snack: Doritos", 339 | "Most unusual job: Working as a Serf at Medieval Times" 340 | ], 341 | "firstName": "Mike", 342 | "lastName": "Skutta" 343 | }, { 344 | "id": "ian-tannehill", 345 | "title": "Developer", 346 | "image": "http://onenorth.blob.core.windows.net/keystone/Ian_Tannehill.jpg", 347 | "bio": "As a Developer at One North, Ian provides technical assistance to both new and ongoing clients at One North. He brings over four years of experience in full stack development to his role. Ian attended Marquette University, receiving a Bachelors of Science in Computer Engineering.", 348 | "facts": [ 349 | "Fun fact: Every school I have attended has had some type of bird as the mascot (eg. Cardinal, Falcon, Eagle, Golden Eagle)." 350 | ], 351 | "firstName": "Ian", 352 | "lastName": "Tannehill" 353 | }, { 354 | "id": "rick-tham", 355 | "title": "Director, Technology", 356 | "image": "http://onenorth.blob.core.windows.net/keystone/rick-tham.jpg", 357 | "bio": "Rick Tham is the Director of Technology at One North, working to research, test and integrate new technologies for both One North and our clients. Rick is the only Rick at our company…and, yes, this was his fun fact.", 358 | "facts": [ 359 | "Favorite movie: Ferris Bueller's Day Off. Before I moved to Chicago, this movie was my main source of things to do in Chicago.", 360 | "What you wanted to be when you were little: A doctor, but I guess my patients are now just applications. They get sick too." 361 | ], 362 | "firstName": "Rick", 363 | "lastName": "Tham" 364 | }, { 365 | "id": "erik-thiem", 366 | "title": "Associate Developer", 367 | "image": "http://onenorth.blob.core.windows.net/keystone/Eric_F.jpg", 368 | "bio": "Associate Developer Erik contributes to his team daily, using his skill-set to assure websites function properly as well as continually updating, monitoring and renovating client projects.  He works hard to help make certain technology solutions are up to the highest standards to ensure client satisfaction. ", 369 | "facts": ["Favorite hot sauce: Cholula Chili Garlic", 370 | "Favorite hobbies: Bicycling, cooking and learning new languages (currently decent at Spanish and attempting to learn French)" 371 | ], 372 | "firstName": "Erik", 373 | "lastName": "Thiem" 374 | }, { 375 | "id": "jimmy-tsao", 376 | "title": "Senior Front-End Developer", 377 | "image": "http://onenorth.blob.core.windows.net/keystone/Jimmy-Tsao_BW.jpg", 378 | "bio": "Jimmy is a Senior One North Front-End Developer with advanced experience in both web development and technical consulting. He solves problems for our clients through appealing web pages and digital design.", 379 | "facts": [ 380 | "Favorite season: Spring because everyone is happier once winter is over.", 381 | "Favorite breakfast food: Ham, egg and cheese on a croissant." 382 | ], 383 | "firstName": "Jimmy", 384 | "lastName": "Tsao" 385 | }, { 386 | "id": "dom-vespo", 387 | "title": "Senior Systems Engineer", 388 | "image": "http://onenorth.blob.core.windows.net/keystone/dom-vespo.jpg", 389 | "bio": "As a Senior Systems Engineer, Dom is responsible for the configuration, maintenance and 24/7 support of our clients’ digital experiences. He has extensive experience deploying and supporting custom web applications in a production environment. He is also a die-hard White Sox fan (what else do you need to know to love him?).", 390 | "facts": [ 391 | "Favorite breakfast food: Bacon. That is the only acceptable answer.", 392 | "What you wanted to be when you were little: A professional baseball player" 393 | ], 394 | "firstName": "Dom", 395 | "lastName": "Vespo" 396 | }, { 397 | "id": "matt-weeks", 398 | "title": "Developer", 399 | "image": "http://onenorth.blob.core.windows.net/keystone/Matt-Weeks_BW.jpg", 400 | "bio": "As a Developer at One North, Matt works with a strong knowledge of programming technologies and JavaScript libraries to implement full stack development on new and existing projects.", 401 | "facts": [ 402 | "Fun fact: I love playing music and songwriting. My main instruments are acoustic and electric guitar.", 403 | "Favorite movie: Wolf of Wall Street" 404 | ], 405 | "firstName": "Matt", 406 | "lastName": "Weeks" 407 | }, { 408 | "id": "chris-wigley", 409 | "title": "Solutions Architect", 410 | "image": "http://onenorth.blob.core.windows.net/keystone/Chris-Wigley_BW.jpg", 411 | "bio": "As a Solutions Architect at One North, Chris provides sound and atypical reasoning to complex problems as well as assistance with analytics, responsive web design, mobile development and performance optimization. With several years of knowledge and expertise in the field, he provides both guidance to his peers and results that both meet and exceed client expectations.", 412 | "facts": [ 413 | "Fun fact: I play guitar/sing. I was in a touring band for seven years during and immediately post-college.", 414 | "Favorite color: Blue" 415 | ], 416 | "firstName": "Chris", 417 | "lastName": "Wigley" 418 | }] 419 | --------------------------------------------------------------------------------