My previous portfolio website was built with VueJS using a template that leveraged Bootstrap 4. From my previous experience I had some pain points I wanted to address in this new iteration. I wanted to integrate some features that would futureproof the core content and components of the portfolio. I also wanted to take this opportunity to test out how transferrable my experience with StencilJS is with React and get a chance to try some things creatively that I haven't had an opportunity to in my work projects.
Previous VueJS portfolio
Overall strategic goal
Create a bespoke portfolio website using a React framework. Structure the project in a way that is easy to maintain, utilizes reusable components, fast in writing article content, and allows freedom to style and create interactive templated sections. To see the code of this portfolio website see my Bitbucket repo.
- Responsive (Phone, Tablet, Desktop)
- Utilize design patterns
- Visually striking and dynamic Hero that responds to user interaction
- Single main page with automatically generated projects section from markdown files
- Accessible (Color contrast ratios, Semantic HTML hierarchy)
- Component driven
- Article content in markdown format separated from front-end (Headless CMS)
- Utilize Typescript
- Nimble, customizable and lightweight CSS library
Staying on track
I broke down the project into tasks and organized them in importance to the outcome of this portfolio using Trello. I needed to timebox and prioritize each task in order to ensure I gave enough attention to my write-ups and keep focus despite my excitement for solving design problems and coding out new features. I also used Trello to captured bugs and ideas that came up during development.
Using Trello to manage my project allowed me to:
- Keep track of how long I'm spending on particular tasks
- Break up each task into categories
- Order backlog items in importance
- Stay motivated by tracking progress
Starting with the Design
I started by defining what I wanted to accomplish with the portfolio project:
Create a portfolio that helps my audience get a feel for who I am and how I can contribute to their team.
I started with research. Getting inspired by other Front-End portfolios as well as looking at job boards to see what kind of roles appeal to me and how I can demonstrate ways I can contribute to their team.
I did a mood board on InVision (useful for creating quick moodboards) and captured:
- Transitions/Animation styles that I thought expressed what I wanted to go for
- Layout options for how to organize the kind of content I was envisioning
- Successful project cards (summary of project details)
I started by sketching out low-fidelity wireframes on paper to visualize different ways I wanted to lay out the content responsively. This allowed me to focus on strategizing what content was the most important and how to visually present this information to my audience across different breakpoints (phone, tablet and desktop):
- Hero - something to express my design aesthetic and help me distinguish myself from other portfolios
- About me - work experience, skills
- Past Projects section - short summaries with associated skills and roles
- Project Writeup - articles explaining my thought process for each project highlight
Next I used Adobe XD to create mockups and a functioning prototype to finalize the spacing cadence, content presentation, typographic hierarchy and color palette. Once I was done mocking up and iterating between each viewport I began development.
During development I would iterate on the mockup as design choices needed updating.
For example, I would go back to Adobe XD to finalize the look and feel of the Label component:
After some research I landed on Gatsby because it was open-source, React-based, and used GraphQL. This toolkit allowed for templating, content management, component based architecture, and flexibility to implement all the custom design requirements.
What I enjoyed
- Decoupled written content and front-end: Gatsby has a feature with GraphQL that allows it to consume Markdown and generate templated HTML content with automatic routing. I am able to keep written content and the front-end structure completely decoupled allowing more flexibility and much easier writing and editing blog type content.
- The power of GraphQL to apply content strategy: GraphQL allows me to simplify presentation logic. By utilizing GraphQL's ability to query and filter my MarkdownFiles based on my frontmatter, I was able to control how each project was presented and laid-out when combined with React.
- TailwindCSS: I felt TailwindCSS was a great decision, as the utility class based approach saved a lot time, was easy to customize, and provided great responsive and grid utilities. Since I was building the project from the ground up, it kept my project clean from bloat of unused components that came with a traditional CSS library like Bootstrap.
- Gatsby has great support: I ended up using additional plugins like
gatsby-plugin-react-helmet, and found it was really simple to bring on a library like lodash via
- React: I enjoyed using React and there were similar concepts to StencilJS like
Children and its componentLifeCycle that enabled me to hit the ground running faster. I found that passing
Props was a powerful tool in the case of my
Hero component that prevented the entire section to redraw but can give some fine-tuning on what components to update as user interaction was occurring.
- Typescript: Typescript saved me a lot of time debugging and the built-in autofill and code-referencing is worth the time I found to get it integrated and typing correctly. It did require some finagling to get it working perfectly with Gatsby and React, such as how to define Interfaces for my Markdown content and getting it to work between React functions and classes.
- Using CSS to 3D: I decided to use CSS to create the effect of having the devices animate in 3D space versus using three.js. It meant a lighter page load, native support across modern browsers, and much faster development time to tweak animations. Practically it also meant I could reuse the graphics created with HTML and CSS positioned above other content, unlike with three.js where it requires a
- iOS Perspective Bug Having opted to go for animating in 3D space using CSS, I was surprised to see that Safari on my Mac test device was having visual errors with the rendering of the iPad and phone graphics in the hero. Turned out after debugging it was due to the way iOS was handling the CSS property
perspective and the way it handled
- Performance: Initially I included an animation on the screen of the iPhone and iPad in the hero section using CSS. I was animating three layers of waves as an SVG that was animating via CSS in a parallax. My initial assumption was that any kind of transform CSS is performant, because it utilized the GPU. I learned that possibly because the animation was 3D transformed as well, it took a toll on the GPU and older devices, so I needed to forgo it.
- Throttling Scroll Listener: At first I wired up the components so that at each scroll, my iPad and iPhone would be animating in 3D space incrementally based on the distance. While not as performance heavy as the waves animation above, I ended up optimizing it by using lodash's
throttle and moving to a CSS key frame based animation rather than incrementally setting its transform properties which maximized the performance.
Working with Gatsby and GraphQL to build my Portfolio website was an excellent experience. There was enough documentation where I never felt stuck or felt like I couldn't fix a particular problem. I've found that having a background in component driven frameworks like StencilJS or Angular helped quickly get me hitting the ground running. Finally building out the project with React components as well as separating the written content in Markdown files ensured that the core-content can be easily reused in the future.