Build a portfolio site with Contentful, Next.js and Netlify
![PortfolioWebsite](https://images.ctfassets.net/fo9twyrwpveg/3RWJKchDbiwyq0YcuAo8Mw/6b97beabf4f1e6d9c5f756f4c9ad7ac8/PortfolioWebsite.png?fm=jpg&q=90&w=1536)
When I wanted to make my portfolio site fast and easy to maintain, I landed on the following solution to create a static site using Contentful as my content manager, Next.js to display the data, and Netlify for hosting.
Requirements of the site
Fast ⚡️
Secure 🔒
Maintainable 🏗
Easy to deploy 🚀
Service Worker ⚙️
Goal
By the end of this you should have a good understanding of how I got to this website:
![img1](https://images.ctfassets.net/fo9twyrwpveg/aaBkADG8la6yU8CAg8U2a/7ca7c51c3be71d0d34566929ac5da6cb/img1.png)
Contentful
With an empty space, we are going to start to add our content types:
![img2](https://images.ctfassets.net/fo9twyrwpveg/3HLpMI4YPCscKMwSWGy2i4/13b9477f406667d4616ad408302b0348/img2.png)
The main focus on this site is the work items, so we’ll go ahead and add a new content type called Work.
![img3](https://images.ctfassets.net/fo9twyrwpveg/p6uQDlMLHEeKCii2O8YOY/9896c9ebe8c2c7c815da8b958df817da/img3.png)
Next, we need to add the fields into the work content type. But what fields exactly do we need to add? Let's open up that previous build of the site.
![img4](https://images.ctfassets.net/fo9twyrwpveg/8ZMnmIEQgg4uyeoeECQ20/f9e1ec1508ea20943862571bbbbba20a/img4.png)
If we look back at the previous build of the site, we can check what fields we need for our content type:
![img5](https://images.ctfassets.net/fo9twyrwpveg/7sWHVCR5gkQkue2UuqCiMS/b0748afba63cbe0ccccaa42131d93d49/img5.png)
Looks like we will need:
Featured image
Logo
Title
Description
Color
Link
Now go ahead and add those into Contentful:
![img7](https://images.ctfassets.net/fo9twyrwpveg/4B6XxLLqVGSWeMukwouWeM/ecde5f23c41b405814c482c0405be969/img7.png)
Now that we have our content model setup, we can go through, create and fill out all of the work posts in the content area:
![img8](https://images.ctfassets.net/fo9twyrwpveg/1BXaf9mosMIKEAQWC8OYaa/757f012a39dc40b634783bd517250b18/img8.png)
One more thing to note, I have actually created a custom content model for the Homepage. This has a title and then just a Work field which has a 'many reference' attribute.
![img9](https://images.ctfassets.net/fo9twyrwpveg/32JHcrZWUMyOmeoCcMIiwE/1a274660770fc90916265d833830c5c3/img9.png)
This only exists so I can do some sorting with the nice drag-and-drop functionality that Contentful allows:
![img10](https://images.ctfassets.net/fo9twyrwpveg/2W0UXqDJuoMUEQkYSCuGUk/613d32a0b154856f13f327ff9eba8442/img10.png)
Now we have all our content in Contentful, let’s head over to our command line and code editor, open up a new project to grab the content and create some React components to display it.
Next.js
We can create a new project, via the command line, and then move things into it.
I’m going to open up my code editor and drop in a package.json
file with an empty object inside so when we run the next command, the dependencies will actually save to that new package.json
file.
Following that, a visit to the Next.js repo lets me find the next command to get moving:
I’m going to run that script to install the dependencies; that will also automatically save those dependencies to my package.json
file.
![img13](https://images.ctfassets.net/fo9twyrwpveg/dCfYaR7trG8smCMIQaA8U/2b10ace79471da69b519549ab9a258eb/img13.png)
I’ve gone ahead here, put in the scripts to build for production, and develop the project locally.
![img14](https://images.ctfassets.net/fo9twyrwpveg/34boWkirygagqCE6A4U84E/af274bd6103343a7a2859082e1752134/img14.png)
That’s it for configuration. We are ready to create a page, and then create a few components to put on that page!
We will start by creating a folder called pages, which Next.js recognises as a route, and then creating our index page inside that folder; that will be our homepage.
![img15](https://images.ctfassets.net/fo9twyrwpveg/6jepiKoluEeyWUOQMCWeSY/b520f121883bf4e832feb8d5b5ec32de/img15.png)
Now that we have that, let’s run the project locally and visit localhost:3000 in the browser:
![img16](https://images.ctfassets.net/fo9twyrwpveg/6L6GhqOecwqumCwU0imCAW/7c33cdd4eb2320cc034fdd79ae95d4d4/img16.png)
Great, now we need to get our Contentful data. I have a little script I’m going to run which will request that from Contentful and then write it to disk. The reason I’m doing it this way is to make everything as fast as possible by just reading JSON straight from disk; this also helps with caching later.
This snippet can be found here.
![img17](https://images.ctfassets.net/fo9twyrwpveg/GkN0IxjoEUGem0UWyqEiA/635cbfc289396f66546f207f7d3e40a5/img17.png)
We need to update our package.json
file at this point so we are able to run our postinstall
script.
![img18](https://images.ctfassets.net/fo9twyrwpveg/1QD4mgbYeIeYkuUsUk60M6/70160beae72104705f282220d8847e5a/img18.png)
We need to use a custom .babelrc
file here to utilize the import
/ export
tokens available to us in that getcontent.js
file.
{: .img}
![img19](https://images.ctfassets.net/fo9twyrwpveg/5oV3nu3b3i28CU4KQ0GaQs/ea69aa472d562b2c069c96f542a7480a/img19.png)
Create a new folder from the root of the project for the JSON file to be written to—we will call that data:
The last step here before we can run our postinstall
script would be installing the depedencies:
Phew, ok, let’s run it!
Excellent, we have data from Contentful, written to JSON locally:
![img20](https://images.ctfassets.net/fo9twyrwpveg/6LSgoEyk7KaQU46UC4SA0W/6368817d9cef5f03b043bb0ec9ffe14a/img20.png)
Now, we will display this data using a few React Components. To do that, let's create a components folder, enter it, and create the three main components we will be using:
![img21](https://images.ctfassets.net/fo9twyrwpveg/5iYVEkD4vSw6UGOqau6CIq/f5689fba295d225558d57dbf5deacc19/img21.png)
Back to index.js
, let's render our WorkFeed component and give it the data from Contentful:
Inside WorkFeed, we will loop our data and render a WorkItem for every case-study we have:
Now inside the WorkItem, we move on to render all of our data. This component could actually be broken up into smaller chunks, but as with all personal projects, sometimes you don’t have time to make something perfect:
This snippet can be found here.
![img22](https://images.ctfassets.net/fo9twyrwpveg/4JnubIE7g42Me6KUa8Wa2q/424e70fc9e00dd5655c85a978d518598/img22.png)
I’ve left out some of the styling here for presentation purposes.
Let’s head back to the browser and hit refresh. We should have some data shown in the manner we would like it displayed:
This export command will output our site into a directory called out, which will be important in the next step.
Netlify
Alright, now that we have what we want on the project side, let’s get the site deployed to Netlify. I’ve already version-controlled this site and connected my Bitbucket account to Netlify, which has gone and found the repo for me:
![img23](https://images.ctfassets.net/fo9twyrwpveg/1STel89ulSQq0mmCysyqgi/196d4928d443c2b00f68c4abf027a6a7/img23.png)
Now I can input my build command and publish directory, and hit deploy to get this site live.
![img24](https://images.ctfassets.net/fo9twyrwpveg/2747KSLLWk4kqwWQ8OmGoq/29ac279c7bc14bd1cb46c3ced7e495fa/img24.png)
Here we have it!
![img25](https://images.ctfassets.net/fo9twyrwpveg/4F0d6VHgfmqq4Eguko0mKk/58904ccf3d3e4d501ece3fccd4a11e5f/img25.png)
Netlify + Contentful
At this point, I'd like to show you how to auto-deploy to Netlify whenever we have published or updated anything from inside Contentful.
Let’s head back to Netlify to create a new ‘Build hook’:
![img26](https://images.ctfassets.net/fo9twyrwpveg/2vZKKcMYK4MEeoqcQKC04i/18a03c669cf80ba825de770b0ad301e9/img26.png)
Hit save:
![img27](https://images.ctfassets.net/fo9twyrwpveg/6JFxCR85zOIckMIYiqUkiU/7ff10b2037b7c0202c3bd991cf2e0c16/img27.png)
Excellent, now we have a URL for running deployments from Netlify, which we can copy and place into Contentful.
Let’s head over to Contentful to set up a webhook which will post to the URL we just generated from Netlify:
![img28](https://images.ctfassets.net/fo9twyrwpveg/3m6CrAy8kMSWS6Qgsio0yo/65d2ba716ba557487a72c15a434e7caf/img28.png)
Hit save on that, and we now have our webhook setup to push to Netlify. Let’s give that a quick test:
![img29](https://images.ctfassets.net/fo9twyrwpveg/61qvoNx9TiAsOcqsgGaU2m/0400ad3d924d0a961674d1205dac457f/img29.png)
![img30](https://images.ctfassets.net/fo9twyrwpveg/1RFP768ZmcAiiGIqo4iUei/811fb8d785979afd939dd15cf3c54ef7/img30.png)
![img31](https://images.ctfassets.net/fo9twyrwpveg/XO299c91kcSoU6GgSgA24/143499b4472bc199d55b6ee259d8c8c1/img31.png)
Perfect!
That’s a quick run-down of how to get a portfolio (static) site up and running, using the combination of Contentful, Next.js and Netlify to produce a great static site.
![Tom Sansome](https://images.ctfassets.net/fo9twyrwpveg/2IuMsDQdxSGAE6mEeqkoMy/ca515971b56a9cc7af2363e987310513/tom_s.png?fit=thumb&f=top&w=350&h=350&fm=jpg)