Creating / updating our portfolios is a necessary evil these days. Places change, people change, and thus the cycle of content creation and management churns continuously. When you find yourself in need of a portfolio redesign, there are tons of tools and services to consider. One that should currently peak your interest is the Gatsby JS static site generator along with a headless CMS, like Cosmic JS. Today, with these two tools, we will create a working portfolio ready for continuous deployment, with the power to be rebuilt when content changes are made.
We are creating a portfolio site mostly with static data, but it would nice to be able to easily modify the content of our site without needing to modify a bunch of source code. So we are building a client that consumes content stored on a Content Management Service and programmatically displays it at whatever URL we choose.
Gatsby JS - This is a static site generator that will automatically fetch new data and rebuild our site files when changes are made to our content. Comes bundled with data fetching wizardry GraphQL and the ever present React JS front end framework.
Cosmic JS - Our Content Management Service that will store all the information we need about our site. Cosmic JS offers very flexible data model definition that will allow us to store all types of information, from iterables to simple text fields and HTML content. NOTE! - In order to follow along with this tutorial you will need to create a bucket on Cosmic JS and fill it with the appropriate data objects.
RSuite - A library of pre-styled components that works with react to give us pre-styled components. This will allow us to use components that look great out of the box, while also giving us flexibility to make adjustments as needed.
Netlify (Optional) - A deployment service that will let us hook directly into a git repository. Using this we can configure webooks for rebuilding static files as well as make automatic deploys when source code changes occur.
Let's go ahead and begin configuring our setup.
We only have a few software requirements needed to start building. Mainly we need Node JS either npm or yarn, and we will be using git to do some deployment things on Netlify if you so choose.
Once you get those installed, we can begin setting up our development environment. Gatsby uses a very handy dandy CLI to allow us to bootstrap our project with a project directory ready to build and serve from a Node environment.
If you don't have the CLI you can install it with a simple npm terminal command:
$npm install -g gatsby-cli
This will take a moment to install but after a few seconds you will have access to gatsby terminal command which we can use to initialize our project:
$gatsby new gatsby-portfolio
Now we have a directory called gatsby-portfolio in the location you ran the gatsby command, change to that directory and list its contents:
$cd gatsby-portfolio/ && ls -la
You should see a list of folders and files similar to this:
open up package.json and we will see we have some terminal scripts that we can now use to build / serve our project. Try running the start script in your terminal:
After a few seconds we should see a success message in our terminal and we should be able to view our initial project view on our localhost, you should see something like this:
Great, now press ctrl + C within your terminal to stop the development server and we are now ready install our node libraries.
We require a few plugins from Gatsby to allow our Graphql queries to run, as well as a few extras for environment configuration and our component library RSuite. From within your project directory, we need to run some terminal commands to get our js libraries:
$yarn add rsuite dotenv gatsby-source-cosmicjs gatsby-plugin-sass gatsby- plugin-less node-sass less
Let's go through these and talk about what we are adding to our project here:
- rsuite - our component library that I mentioned above. Installing this let's us import js classes and insert pre-styled React components.
- dotenv - Allows us to configure our source code with sensitive api keys, token, whatever that may change between developers but should be present when the source code is built.
- gatsby-source-cosmicjs - a gatsby plugin that will let us easily make graphql requests to the Cosmic JS graphql API.
- gatsby-plugin-sass / gatsby-plugin-less / node-sass / less - Gatsby plugins and styling libraries that will let us use .scss and .less files. These will allow us to import rsuite styling specs and bundle them properly on build.
In order for Gatsby to be able to build our html files, we need to fetch data from Cosmic JS and build each page using the data graphql retrieves. Let's go ahead and open gatsby-config.js and add our installed packages:
The first thing you you should notice is our requiring of
dotenv. This will make our environment variables accessible in this config file at run time and allow Gatsby to configure our components with our credentials needed to make API requests.
We have added our plugins for sass and less, and also added our gatsby-source-cosmicjs plugin. You'll notice that we are using some environment variables to configure this plugin so we need to add a hidden file that will store these variables.
Now add your variables to this file and dotenv will take care of defining these using line 1 of our gatsby-config.js file. You can find the value to assign to these variables from within your Cosmic JS bucket: Bucket Name > Dashboard > Settings > Basic Settings:
Now we are ready to build!
So what are we building exactly. Well, basically we will create one large Page component and create a series of display components to handle each section of our portfolio. Let's break this down:
- This is our home page and where all of our components will be loaded and used to display portfolio info.
- This will be our projects section that will take project data and display information about each project. This will take a prop composed of our portfolio projects and iterate over them to display data when appropriate.
- This will a section highlighting our skills and the types of services / work we offer to people that might peruse our portfolios.
- This will be a section that talks about us, displaying any personal data we want to share.
- Finally we have a component that we will use for displaying a contact form that will let users email us if they have any inquires.
This is our main component that act as our entry point for our portfolio. Its job is to make several Graphql API requests for our portfolio data from Cosmic JS and pass that data onto the different sections of our portfolio. Let's look at the component and talk about what's happening:
The only display element that really lives here is the splash screen which gives us a little bit copy that can be displayed about your company. But the meat of our content will be pushed into each section component.
Now let's update the header so that we can navigate around our home page.
By default Gatsby gives us a Layout component that lets us wrap each page with a Header and Footer. We are going to add some navigation for our portfolio into the header so users can navigate to different sections of our Portfolio by clicking on a nav bar that we will import from rsuite:
These links will scroll the home page down to each section via the name properties placed on each section on our home page.
This component takes in our data about any services we provide, specifically a names, a short summary, and a more in depth description, and let's us display that to our users:
This iterates through our services objects. For every service that exists we add a new div to the work component section. Now we can modify and add data to our services on Cosmic JS and it will update accordingly.
These sections will behave in essentially the same way, we display some information from our Home page object from Cosmic JS. Just a bit of text to give the user some context for each section, but after that we just iterating through our list objects we have saved to our Cosmic JS bucket.
Here’s our Projects component that will iterate through our projects and display images and text:
The about component will behave the same way. It will iterate through a list of people and display some images and information stored in the services objects on Cosmic JS:
Lastly we have a component that will users to contact us at an email we specify. This will handle our contact form, and will be initialized with some state variables so we can control our user inputs, all the input and form components are handled by rsuite so we don't have to add too many styling properties to our form fields and feedback components:
Essentially we validate our form fields by checking if all the form field contain a value, then we use a the mailto url to open an email client and populate it with our message.
Now we are ready to deploy our app. The most important part of this process is making sure that our app rebuilds itself when we change any data on Cosmic JS. If we integrate continuous deployment using git Netlify will allow us to activate a buildhook in order to generate new static files using updated data fetched from the Cosmic JS API.
Go to Netlify and create an account if you don't aready have one. From the apps dashboard click New Site from Git at the app dahsboard. From there you will be walked through the process of authorizing Netflify to access a repository from a git service (github, gitlab, bitbucket).
You will have to add you COSMIC_READ_KEY and your COSMIC_BUCKET_SLUG as environment variables. This can be found under the deploy settings once the app has been created on Netlify. In the same area you can create your buildhook to allow Cosmic JS to request a rebuild of your files once an update is made:
Once the buildhook is created go over to Cosmic JS and add it to the webhooks tab under the settings for your bucket:
Follow the instructions for adding a webhook that fires a post request to that url from Netlify every time an object is updated and you should have a continuously deployed, super fast portfolio site ready to be updated.
Thanks for following along with me and I'll see you next time I decide to build something cool :)