HTMLify
professional-portfolio.html
Views: 12 | Author: cody
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 | <!DOCTYPE html> <html lang="en" dir="ltr" data-cast-api-enabled="true"> <head> <!-- META --> <meta charset="UTF-8"> <meta http-equiv="Content-Language" content="en"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- Primary Meta Tags --> <title>Professional Portfolio Project Walkthrough</title> <meta name="title" content="Professional Portfolio Project Walkthrough"> <meta name="author" content="Jacob Grisham"> <meta name="keywords" content="Jacob,Grisham,Jacob Grisham,Professional Portfolio"> <meta name="description" content="Walkthrough of my project Professional Portfolio. My Professional Portfolio is built with HTML, SASS, Javascript and hosted on Netlify."> <!-- Open Graph / Facebook --> <meta property="og:locale" content="en_US"> <meta property="og:type" content="website"> <meta property="og:url" content="https://www.jacobgrisham.com/"> <meta property="og:title" content="Professional Portfolio Project Walkthrough"> <meta property="og:site_name" content="Jacob Grisham Professional Portfolio"> <meta property="og:image" content="https://www.jacobgrisham.com/img/thumbnail.png"> <meta property="og:image:secure_url" content="https://www.jacobgrisham.com/img/thumbnail.png"> <meta property="og:image:type" content="image/png"> <meta property="og:image:height" content="630"> <meta property="og:image:width" content="1200"> <meta property="og:image:alt" content="Professional Portfolio"> <meta property="og:description" content="Walkthrough of my project Professional Portfolio. My Professional Portfolio is built with HTML, SASS, Javascript and hosted on Netlify." name="description"> <meta property="fb:app_id" content="2733409333567092"> <!-- Twitter Meta Tags --> <meta property="twitter:card" content="summary_large_image"> <meta property="twitter:url" content="https://www.jacobgrisham.com/"> <meta property="twitter:title" content="Professional Portfolio Project Walkthrough"> <meta property="twitter:description" content="Walkthrough of my project Professional Portfolio. My Professional Portfolio is built with HTML, SASS, Javascript and hosted on Netlify."> <meta property="twitter:image" content="https://www.jacobgrisham.com/img/thumbnail.png"> <!-- SEO --> <link rel="canonical" href="https://www.jacobgrisham.com/pages/projects/professional-portfolio.html"> <!-- FONTS --> <link href="https://fonts.googleapis.com/css2?&family=Montserrat:wght@100;200;300&family=Nunito+Sans:wght@200;300;400&family=PT+Mono&display=swap" rel="stylesheet"> <!-- CSS --> <link rel="stylesheet" href="../css/style.css"> <!-- Include this second link for production --> <link rel="text/css" href="../css/style.css"> <!-- FAVICON --> <link rel="icon" href="../favicon.ico" type="image/x-icon"> <link rel="shortcut icon" href="../favicon.ico"> <link rel="apple-touch-icon" sizes="180x180" href="../favicon_io/apple-touch-icon.png"> <link rel="icon" type="image/png" sizes="32x32" href="../favicon_io/favicon-32x32.png"> <link rel="icon" type="image/png" sizes="16x16" href="../favicon_io/favicon-16x16.png"> <link rel="manifest" href="../site.webmanifest"> </head> <body class="projects-body"> <!-- Loader --> <div class="laptop loader"> <svg class="laptop__svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 79.375 79.375" height="300" width="300"> <g transform="translate(-2.22 3.222)"> <g transform="translate(-335.788 -22.347) scale(.39771)"> <rect fill="#b3b3b3" width="137.583" height="89.958" x="880.884" y="99.204" ry="2.022"/> <rect y="100.527" x="882.207" height="87.313" width="134.938" ry="2.134" rx="0"/> <path d="M886.175 104.496h127v79.375h-127z" fill="#4d4d4d"/> <rect fill="#333" width="29.788" height="70.68" x="891.36" y="113.22" ry="0" rx="0"/> </g> <path d="M16.674 20.813h50.597v.317H16.674zM30.53 24.5h36.617v15.488H30.529zm0-1.555h9.184V24.5H30.53z" fill="#1a1a1a"/> <path d="M30.53 22.69h9.183v.255H30.53z" fill="#003380"/> <rect fill="#2c5aa0" width="6.399" height=".455" x="32.113" y="23.546" ry=".227"/> <path d="M30.534 41.82h36.645v8.972H30.534zm-.005-1.557h9.184v1.555H30.53z" fill="#1a1a1a"/> <path d="M30.53 40.007h9.183v.256H30.53z" fill="#003380"/> <rect fill="#2c5aa0" ry=".227" y="40.793" x="32.089" height=".455" width="6.399"/> <g transform="translate(-19.725 -1.116) scale(.39771)" fill="#ccc"> <rect ry=".767" y="62.346" x="99.493" height="1.535" width="14.902"/> <rect width="14.902" height="1.535" x="103.298" y="65.818" ry=".767"/> <rect width="16.379" height="1.535" x="106.895" y="69.291" ry=".767"/> <rect width="11.497" height="1.535" x="106.959" y="72.763" ry=".767"/> <rect ry=".767" y="76.235" x="107.055" height="1.535" width="11.497"/> <rect ry=".767" y="79.707" x="106.927" height="1.535" width="11.497"/> <rect ry=".767" y="83.179" x="102.833" height="1.535" width="16.379"/> <rect ry=".767" y="86.651" x="102.746" height="1.535" width="13.001"/> <rect ry=".767" y="90.123" x="106.991" height="1.535" width="16.379"/> <rect ry=".767" y="93.595" x="107.338" height="1.535" width="9.882"/> <rect ry=".767" y="97.067" x="100.024" height="1.535" width="16.379"/> <rect ry=".767" y="100.539" x="100.196" height="1.535" width="12.74"/> <rect ry=".767" y="104.011" x="100.379" height="1.535" width="12.44"/> </g> <g transform="translate(-411.355 -23.965) scale(.39771)"> <rect fill="#ccc" ry=".887" y="193.745" x="1056.522" height="4.151" width="166.317"/> <path fill="#999" d="M1222.19 197.896h-165.048l4.029 2.723h156.468z"/> </g> <rect fill="#b3b3b3" ry=".4" y="53.067" x="38.233" height=".801" width="7.35"/> <rect fill="#999" ry=".4" y="43.091" x="31.651" height=".801" width="10.779"/> <rect fill="#999" width="10.779" height=".801" x="31.651" y="45.052" ry=".4"/> <rect fill="#999" width="10.779" height=".801" x="31.651" y="47.013" ry=".4"/> <rect fill="#999" width="10.779" height=".801" x="31.651" y="48.975" ry=".4"/> <rect fill="#999" ry=".051" y="49.718" x="43.875" height=".103" width="1.511"/> <rect fill="#999" width="5.07" height=".801" x="43.661" y="43.181" ry=".4"/> <rect fill="#999" width="13.784" height=".801" x="43.683" y="45.152" ry=".4"/> <rect fill="#999" width="10.779" height=".801" x="43.703" y="46.958" ry=".4"/> <rect fill="#c83737" width="4.572" height=".61" x="31.725" y="25.832" ry=".305"/> <rect fill="#fd5" width="8.157" height=".61" x="37.883" y="25.823" ry=".305"/> <rect fill="#fd5" ry=".305" y="27.46" x="37.922" height=".61" width="10.535"/> <rect fill="#fd5" ry=".305" y="29.214" x="37.922" height=".61" width="6.053"/> <rect fill="#999" width="10.779" height=".801" x="31.751" y="30.95" ry=".4"/> <rect fill="#ccc" ry=".325" y="32.771" x="31.771" height=".649" width="3.93"/> <rect fill="#c83737" ry=".305" y="32.771" x="36.627" height=".61" width="4.572"/> <rect fill="#5fbcd3" width="6.053" height=".61" x="42.045" y="32.731" ry=".305"/> <rect fill="#ccc" width="3.93" height=".649" x="48.951" y="32.672" ry=".325"/> <rect class="code" id="code-8" fill="#fd5" width="6.053" height=".61" x="35.771" y="34.449" ry=".305" /> <rect class="code" id="code-7" fill="#5fbcd3" ry=".305" y="34.5" x="42.27" height=".61" width="9.509" /> <rect class="code" id="code-6" fill="#ccc" ry=".325" y="36.08" x="38.948" height=".649" width="3.93" /> <rect class="code" id="code-5" fill="#37c871" ry=".325" y="36.08" x="44.106" height=".649" width="2.847" /> <rect class="code" id="code-4" fill="#37c871" ry=".325" y="36.131" x="47.923" height=".649" width="2.692" /> <rect class="code" id="code-3" fill="#5fbcd3" ry=".325" y="36.131" x="51.585" height=".649" width="6.097" /> <rect class="code" id="code-2" fill="#ccc" width="3.93" height=".649" x="35.904" y="37.834" ry=".325" /> <rect class="code" id="code-1" fill="#c83737" width="7.203" height=".61" x="41.102" y="37.905" ry=".305" /> </g> </svg> </div> <div class="projects-body__focus-container"> <!-- HEADER --> <section> <h1 class="projects-body__main-heading">Professional Portfolio Project Walkthrough</h1> <h2 class="blog-body__sub-heading">July - September 2020</h2> <h2 class="projects-body__heading">Source Code <span> <a href="https://github.com/JacobGrisham/Professional-Portfolio" aria-label="link to Professional Portfolio source code" target="_blank" rel="noopener noreferrer"> <svg class="skills-box__header-icon"> <use xlink:href="../img/sprite.svg#icon-github"></use> </svg> </a> </span> </h2> <div> <img src="../img/PortfolioMetaImage-min.png" class="projects-body__image lax"></img> </div> </section> <!-- ABOUT --> <section> <h2 class="projects-body__heading">About</h2> <p>My portfolio fundamentally revolves around my other projects. Focused on showcasing a select few with high-quality standards. The core of the application was built from December 2020 - January 2021, with sporadic updates up until January 2023.</p> </section> <!-- PRODUCT FEATURES AND SPECIFICATIONS --> <section> <h2 class="projects-body__heading">Product Features and Specifications</h2> <ul class="projects-body__list"> <li>Custom loading page animation for home page and project pages. Animation is supposed to simulate a developer writing code in an Integrated Development Environment on a MacBook Pro. Art style is a cross between graphic design and illustration to abstract away unnecessary details.</li> <li>For projects that leveraged AdobeXD for wireframing or prototyping, embedded an interactive AdobeXD on the webpage. Furthermore, positioned the iframe over a hyper-realistic SVG image of an iPhone and MacBook Pro to further simulate the experience of interacting with the content in its native device.</li> <li>For full-stack projects, created diagrams of code architecture, database schema, and production system architecture with <a href="https://www.draw.io/" class="curriculum__link" target="_blank" rel="noopener noreferrer">draw.io</a>.</li> </ul> </section> <!-- TECHONOLOGIES --> <section class="technologies"> <h2 class="projects-body__heading technologies__header">Technologies</h2> <div class="skills-box__no-shadow"> <h4 class="skills-box__header"> <svg class="skills-box__header-icon"> <use xlink:href="../img/sprite.svg#icon-embed2"></use> </svg> Front-End </h4> <ul class="skills-box__list"> <li class="skills-box__item"> <svg class="skills-box__icon"> <use xlink:href="../img/sprite.svg#icon-html5"></use> </svg> HTML5 </li> <li class="skills-box__item"> <svg class="skills-box__icon"> <use xlink:href="../img/sprite.svg#icon-sass"></use> </svg> Sass </li> <li class="skills-box__item"> <svg class="skills-box__icon"> <use xlink:href="../img/sprite.svg#icon-javascript"></use> </svg> Javascript ES6+ </li> <li class="skills-box__item"> <svg class="skills-box__icon"> <use xlink:href="../img/sprite.svg#icon-jquery"></use> </svg> jQuery </li> </ul> </div> <!-- Testing --> <div class="skills-box__no-shadow"> <h4 class="skills-box__header"> <svg class="skills-box__header-icon"> <use xlink:href="../img/sprite.svg#icon-lab"></use> </svg> Testing </h4> <ul class="skills-box__list"> <li class="skills-box__item"> <svg class="skills-box__icon"> <use xlink:href="../img/sprite.svg#icon-lighthouse"></use> </svg> Google Lighthouse </li> </ul> </div> <!-- DEVELOPMENT --> <div class="skills-box__no-shadow"> <h4 class="skills-box__header"> <svg class="skills-box__header-icon"> <use xlink:href="../img/sprite.svg#icon-cogs"></use> </svg> Development </h4> <ul class="skills-box__list"> <li class="skills-box__item"> <svg class="skills-box__icon"> <use xlink:href="../img/sprite.svg#icon-git"></use> </svg> Git </li> <li class="skills-box__item"> <svg class="skills-box__icon"> <use xlink:href="../img/sprite.svg#icon-github"></use> </svg> GitHub </li> <li class="skills-box__item"> <svg class="skills-box__icon"> <use xlink:href="../img/sprite.svg#icon-codacy"></use> </svg> Codacy </li> <li class="skills-box__item"> <svg class="skills-box__icon"> <use xlink:href="../img/sprite.svg#icon-codeclimate"></use> </svg> CodeClimate </li> </ul> </div> <!-- PRODUCTION --> <div class="skills-box__no-shadow"> <h4 class="skills-box__header"> <svg class="skills-box__header-icon"> <use xlink:href="../img/sprite.svg#icon-cloud-upload"></use> </svg> Production </h4> <ul class="skills-box__list"> <li class="skills-box__item"> <svg class="skills-box__icon"> <use xlink:href="../img/sprite.svg#icon-netlify"></use> </svg> Netlify </li> <li class="skills-box__item"> <svg class="skills-box__icon"> <use xlink:href="../img/sprite.svg#icon-google-domains"></use> </svg> Google Domains </li> <li class="skills-box__item"> <svg class="skills-box__icon"> <use xlink:href="../img/sprite.svg#icon-google-analytics"></use> </svg> Google Analytics </li> </ul> </div> </section> <!-- UX/UI MOCKS AND GRAPHIC DESIGN --> <section> <h2 class="projects-body__heading">UX/UI Mocks and Graphic Design</h2> <p class="projects-body__paragraph-spacing-below">Used open-souce SVG assets from <a href="https://simpleicons.org/" class="curriculum__link" target="_blank" rel="noopener noreferrer">simpleicons</a> and from <a href="https://icomoon.io/app/#/select" class="curriculum__link" target="_blank" rel="noopener noreferrer">icomoon</a> and placed them all in a <code>sprite.svg</code> file from the <code>symbol-defs.svg</code> file.</p> <p>Admittedly, I initially mocked this website in a physical notebook. Looking back, given how simple the initial design was, I think this is still appropriate, especially considering that I didn't have to share the mock with any teammates. At this point, it's quaint and nostalgic to think of mocking a website on the proverbial backside of a napkin.</p> </section> <!-- DESIGN AND ARCHITECTURE --> <section> <h2 class="projects-body__heading">Design and Architecture</h2> <h3>Code Architecture</h3> <p class="projects-body__paragraph-spacing-below">Initially built this website with a backend server using <a href="https://expressjs.com/" class="curriculum__link" target="_blank" rel="noopener noreferrer">ExpressJS</a> as the Node.js application framework, which was primarily used for serving the single page and for setting HTTP headers and Content Security Policy. I chose ExpressJS as the Node.js application framework for its simple, lightweight functionality. Furthermore I chose to use it to gain more practice because some companies still use it. When this application had a backend, I had to host it somewhere, so I chose to host it on <a href="https://www.heroku.com/" class="curriculum__link" target="_blank" rel="noopener noreferrer">Heroku</a> due to the simplicity of Heroku as a Platform as a Service (PaaS) solution. At one point, the website was hosted on the Hobby (paid) plan on Heroku to guarantee site reliability uptime. The main problem with this overall approach was that it was both heavy and expensive. It was heavy in that ExpressJS wasn't strictly neccessary just to serve a single page. It was expensive in that the Hobby plan was $7 per month. Therefore, after learning about the <a href="https://jamstack.org/" class="curriculum__link" target="_blank" rel="noopener noreferrer">Jamstack</a>, I refactored this application by migrating from a server-based architecture with ExpressJS to a static website architecture with simple HTML. I switched cloud-hosting providers from Heroku to Netlify. The code is more simple and efficient, the website has better performance, and the cloud-hosting provider is free.</p> <p class="projects-body__paragraph-spacing-below">Initially utilized a one-page layout to force creativity in front-end capabilities. In particular, the information in the project pages used to be available only through a modal popup. This certainly forced some implementation creativity for the front-end. However, when I had ideas for making the project pages more content-rich and even interactive, the little modal window started to prove to be a bottleneck. Furthermore, the Google web crawler was not able to index the crucial information in the modal because in the implementation, I had to set the <code>display</code> to <code>none</code> in order to hide it until a user clicked on a button to show it.</p> <p class="projects-body__paragraph-spacing-below">Instead of using a CSS framework like Boostrap, I created all the CSS features from scratch for greater control and customization. I chose to use Sass as the CSS superscript for a few reasons. One was to facilitate using BEM notation. More importantly though, using Sass has a few more useful features than plain CSS, such as the ability to use a <code>@mixin</code>. I also chose Sass because at the time I was unaware of native CSS variables. Regarding the display, I employed a combination of CSS float, flex, and grid properties to gain practice with using each of these approaches. I ensured that the entire website was responsive and used a desktop-first construction methodology. Looking back, I would use a mobile-first construction methodology instead to slightly decrease load time. Optimized responsive design for 8 screen sizes largely following the Google Chrome default screen size breakpoints (4K, LaptopL, Laptop, Tablet, Mobile L, Mobile M, Mobile S). At the time I wasn't aware of other options for choosing screen size breakpoints, so I just went with what Google Chrome provides in the Developer Tools. Implemented responsive design with <code>media queries</code>.</p> <p class="projects-body__paragraph-spacing-below">Increased Google Lighthouse performance score from 12 to 88 and decreased DOM Content Loaded time from 10s to 2s using intersection observer and lazy loading for images and video. Then decreased first visit DOM Content Loaded time from 7s to 1s by refactoring the website from using an express.js server to a static site with no web server.</p> <h3>Production System Architecture</h3> <p class="projects-body__paragraph-spacing-below">There are currently two separate code repositories, deployment pipelines, and web domains. One for this website, my portfolio, and another for my <a href="https://www.jacobgrisham.dev/">blog</a>. Both repos use different technology stacks that weren't integrating well with one another, so I isolated my blog and just linked them together with <code>a</code> tags. When I initially created this portfolio, it was at the start of my software engineering journey, indeed I built the core of this website approximately 2 months into learning web development for the first time. So I built this website with raw HTML and only used Sass as an abstraction on top of CSS. When I created my blog, I was 3 years into my software engineering journey, so I had the benefit of experience to choose a tech stack like Gatsby with React for the blog. Integrating Gatsby, particularly <a href="https://www.gatsbyjs.com/starters/gatsbyjs/gatsby-starter-blog/" class="curriculum__link" target="_blank" rel="noopener noreferrer">this specific blog template</a>, with raw HTML was a good challenge, however after a certain point, I felt I was straying away from the core problem, <em>starting</em> a blog in the first place. Therefore, I decided to keep both the code and production system architectures separate. I have plans of building out a new, better portfolio website with React in the future, at which point I'l be able to integrate my portfolio and blog under one codebase, one deployment pipeline, and ultimately one domain. But for now, this overall strategy helps to remove the friction with starting a blog.</p> <div> <img src="../img/Portfolio-Production-Architecture.drawio.svg" alt="Portfolio Production System Architecture Diagram" class="projects-body__image-smaller projects-body__paragraph-spacing-below lax"></img> </div> </section> <!-- PRODUCTION METRICS --> <section> <h2>Production System Cost</h2> <ul class="projects-body__list"> <li>Netlify Starter Plan: free</li> <li>Google Domain for jacobgrisham.com and jacobgrisham.dev: $26/year</li> <li>GitHub Free Tier: free</li> </ul> <h2 class="projects-body__heading">Production Metrics</h2> <ul class="projects-body__list"> <li><span class="projects-body__bold-text">Traffic</span>: 300+ total website visits since launch</li> <li><span class="projects-body__bold-text">Search Engine Optimization (SEO)</span>: achieved Google PageRank #1 for the search term “jacob grisham”</li> <li><span class="projects-body__bold-text">Site Reliability</span>: 100% uptime service-level indicator (SLI)</li> <li><span class="projects-body__bold-text">Security</span>: Increased Mozilla Observatory security grade from ‘F’ to ‘B-’ using HTTP Headers, HSTS, and Content Security Policy</li> <li><span class="projects-body__bold-text">Performance</span>: from Google Lighthouse</li> <li><span class="projects-body__bold-text">Accessibility</span>: from Google Lighthouse</li> <li><span class="projects-body__bold-text">Cross-Browser Compatibility</span>: used LambdaTest to automatically test this website on different browsers (Chrome, Firefox, Sarfari, and Microsoft Edge) and for different versions of those browsers</li> </ul> </section> <!-- LESSONS LEARNED --> <section> <h2 class="projects-body__heading">Lessons Learned</h2> <ul class="projects-body__list"> <li>Performance, Security, Accessibility, and SEO optimization with <a href="https://developers.google.com/web/tools/lighthouse" class="curriculum__link" target="_blank" rel="noopener noreferrer">Lighthouse</a>. Increased Google Lighthouse performance score from 12 to 88</li> <li>Decreased average DOM Content Loaded time from 10s to 2s using intersection observer and lazy loading for images and video. Further decreased first visit DOM Content Loaded time from 7s to 1s by refactoring website from using an express.js server to a static site with no web server</li> <li>Increased SEO to achieve Google PageRank #1 for the search term “jacob grisham”. Used Open Graph Meta Properties (og:image, etc.) to help increase ranking</li> <li>User Experience optimization with loading page SVG animation</li> <li>Increased cross-browser compatibility using LambdaTest</li> <li>First time using Google Analytics and first time routing website to a domain name</li> </ul> </section> </div> <!-- FOOTER --> <footer class="footer"> <p class="footer__fun-note">Made with<svg class="footer__icon"><use xlink:href="../img/sprite.svg#icon-heart"></use></svg>in SF</p> <p>Copyright © <time id="date"></time> by Jacob Grisham</p> </footer> <!-- JAVASCRIPT --> <!-- Global site tag (gtag.js) - Google Analytics --> <script async src="https://www.googletagmanager.com/gtag/js?id=G-SV51NLJS21"></script> <script type="text/javascript" src="../js/common.js"></script> </body> </html> |