├── .eslintrc ├── .gitignore ├── .prettierrc ├── LICENSE ├── README.md ├── contributing.md ├── gatsby-config.js ├── gatsby-node.js ├── package-lock.json ├── package.json ├── src ├── components │ ├── BackBtn.js │ ├── Container.js │ ├── ContributeBtn.js │ ├── Footer.js │ ├── PortfolioItem.js │ ├── PortfolioName.js │ ├── PortfolioPage.js │ ├── PortfoliosList.js │ ├── SubTitle.js │ └── Title.js ├── pages │ ├── 404.js │ ├── global.js │ ├── head.js │ └── index.js ├── portfolios │ ├── bruno-simon │ │ ├── bruno-simon.md │ │ └── bruno-simon.png │ ├── danny-garcia │ │ ├── danny-garcia.md │ │ └── danny-garcia.png │ ├── diana-ilithya │ │ ├── diana-ilithya.md │ │ └── ilithya.png │ ├── eli-fitch │ │ ├── eli-fitch-portfolio.png │ │ └── eli-fitch.md │ ├── fabio-ottaviani │ │ ├── fabio-ottaviani-portfolio.png │ │ └── fabio-ottaviani.md │ ├── julian-garnier │ │ ├── julian-garnier.md │ │ └── julian-garnier.png │ ├── louis-hoebregts │ │ ├── louis-hoebregts.md │ │ └── louis-hoebregts.png │ ├── lynn-fisher │ │ ├── lynn-fisher.md │ │ └── lynn-fisher.png │ ├── nick-jones │ │ ├── nick-jones-portfolio.png │ │ └── nick-jones.md │ ├── pierre-reimertz │ │ ├── pierre-reimertz-portfolio.png │ │ └── pierre-reimertz.md │ ├── rogie-king │ │ ├── rogie-king-portfolio.png │ │ └── rogie-king.md │ └── shanteli-martin │ │ ├── shanteli-martin-portfolio.png │ │ └── shanteli-martin.md └── templates │ └── Portfolio.js ├── static ├── cp-screenshot-2.png └── favicon.ico └── yarn.lock /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "wesbos" 4 | ], 5 | "rules": { 6 | "react/prop-types": false 7 | } 8 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # dotenv environment variables file 55 | .env 56 | 57 | # gatsby files 58 | .cache/ 59 | public 60 | 61 | # Mac files 62 | .DS_Store 63 | 64 | # Yarn 65 | yarn-error.log 66 | .pnp/ 67 | .pnp.js 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "endOfLine": "lf", 3 | "semi": false, 4 | "singleQuote": false, 5 | "tabWidth": 2, 6 | "trailingComma": "es5" 7 | } 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 gatsbyjs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Creative Portfolios 🌀 2 | > This project was created with [React](https://reactjs.org/), [Gatsby](https://www.gatsbyjs.org/) and [GraphQL](https://graphql.org/). 3 | - Contributions are more than welcome. Please see [contribution guide](contributing.md). 4 | 5 | ![Creative Portfolios](static/cp-screenshot-2.png) 6 | 7 | ### Portfolios ✨ 8 | - [Danny Garcia](https://danny-garcia.com/) 9 | - [Diana Ilithya](https://www.ilithya.rocks/) 10 | - [Bruno Simon](https://bruno-simon.com/) 11 | - [Lynn Fisher](https://lynnandtonic.com/) 12 | - [Rogie King](https://rog.ie/) 13 | - [Shanteli Martin](https://shantellmartin.art/) 14 | - [Pierre Reimertz](https://www.reimertz.co/) 15 | - [Nick Jones](http://www.narrowdesign.com/) 16 | - [Eli Fitch](http://eli.wtf/) 17 | - [Fabio Ottaviani](http://www.supah.it/) 18 | - [Julian Garnier](https://juliangarnier.com/) 19 | - [Louis Hoebregts](https://mamboleoo.be/) 20 | 21 | ### Install ⚙️ 22 | ``` 23 | npm install / yarn install 24 | ``` 25 | 26 | ### Start 🏃 27 | 28 | ``` 29 | npm run develop / yarn develop 30 | ``` 31 | 32 | ### Build 😷 33 | 34 | ``` 35 | npm run build / yarn build 36 | ``` 37 | -------------------------------------------------------------------------------- /contributing.md: -------------------------------------------------------------------------------- 1 | # Rules: 2 | 1. **Creative Portfolios** IS NOT FOR SELF-PROMOTION! 3 | 2. The content of the portfolio is not relevent. 4 | 3. Please compare your portfolio with the existing ones. 5 | 4. Make sure the portfolio meet any of this descriptors: 6 | - [x] Creative/Cool 7 | - [x] Unique/Original 8 | - [x] Beautiful 9 | - [x] Expertly executed 10 | 11 | # Contribution Guidelines 12 | - Search previous suggestions before making a new one, as yours may be a duplicate. 13 | - Open an issue with the label **new portfolio** that I created with the **name** of the person who's portfolio you submit in the title and the **link** to the portfolio in the description. 14 | - Improvements to the existing code or other features are more than welcome. 15 | 16 | Thank you for contributing 😃 17 | -------------------------------------------------------------------------------- /gatsby-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | siteMetadata: { 3 | title: 'Creative Portfolios', 4 | author: 'Raul Dronca', 5 | }, 6 | plugins: [ 7 | 'gatsby-plugin-react-helmet', 8 | 'gatsby-plugin-react-helmet', 9 | { 10 | resolve: 'gatsby-source-filesystem', 11 | options: { 12 | name: 'src', 13 | path: `${__dirname}/src/`, 14 | }, 15 | }, 16 | 'gatsby-transformer-sharp', 17 | 'gatsby-plugin-sharp', 18 | { 19 | resolve: 'gatsby-transformer-remark', 20 | options: { 21 | plugins: [ 22 | { 23 | resolve: 'gatsby-remark-video', 24 | options: { 25 | width: '100%', 26 | height: 'auto', 27 | preload: 'auto', 28 | muted: true, 29 | autoplay: true, 30 | loop: true, 31 | }, 32 | }, 33 | 'gatsby-remark-relative-images', 34 | { 35 | resolve: 'gatsby-remark-images', 36 | options: { 37 | maxWidth: 750, 38 | linkImagesToOriginal: false, 39 | }, 40 | }, 41 | { 42 | resolve: `gatsby-plugin-styled-components`, 43 | }, 44 | ], 45 | }, 46 | }, 47 | ], 48 | } 49 | -------------------------------------------------------------------------------- /gatsby-node.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | 3 | module.exports.onCreateNode = ({ node, actions }) => { 4 | const { createNodeField } = actions 5 | 6 | if (node.internal.type === 'MarkdownRemark') { 7 | const slug = path.basename(node.fileAbsolutePath, '.md') 8 | 9 | createNodeField({ 10 | node, 11 | name: 'slug', 12 | value: slug, 13 | }) 14 | } 15 | } 16 | 17 | module.exports.createPages = async ({ graphql, actions }) => { 18 | const { createPage } = actions 19 | const portfolioTemplate = path.resolve('./src/templates/Portfolio.js') 20 | 21 | const res = await graphql(` 22 | { 23 | allMarkdownRemark { 24 | edges { 25 | node { 26 | fields { 27 | slug 28 | } 29 | } 30 | } 31 | } 32 | } 33 | `) 34 | 35 | res.data.allMarkdownRemark.edges.forEach(edge => { 36 | createPage({ 37 | component: portfolioTemplate, 38 | path: `/${edge.node.fields.slug}`, 39 | context: { 40 | slug: edge.node.fields.slug, 41 | }, 42 | }) 43 | }) 44 | } 45 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gatsby-starter-hello-world", 3 | "private": true, 4 | "description": "A simplified bare-bones starter for Gatsby", 5 | "version": "0.1.0", 6 | "license": "MIT", 7 | "scripts": { 8 | "build": "gatsby build", 9 | "develop": "gatsby develop", 10 | "format": "prettier --write src/**/*.{js,jsx}", 11 | "start": "npm run develop", 12 | "serve": "gatsby serve", 13 | "test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\"" 14 | }, 15 | "dependencies": { 16 | "babel-plugin-styled-components": "^1.10.6", 17 | "gatsby": "^2.9.8", 18 | "gatsby-image": "^2.2.7", 19 | "gatsby-plugin-react-helmet": "^3.1.13", 20 | "gatsby-plugin-sharp": "^2.2.9", 21 | "gatsby-plugin-styled-components": "^3.1.11", 22 | "gatsby-remark-images": "^3.1.7", 23 | "gatsby-remark-relative-images": "^0.2.2", 24 | "gatsby-remark-video": "^1.2.1", 25 | "gatsby-source-filesystem": "^2.1.5", 26 | "gatsby-transformer-remark": "^2.6.6", 27 | "gatsby-transformer-sharp": "^2.2.5", 28 | "react": "^16.8.6", 29 | "react-dom": "^16.8.6", 30 | "react-helmet": "^5.2.1", 31 | "react-parallax-tilt": "^1.3.27", 32 | "styled-components": "^4.3.2" 33 | }, 34 | "devDependencies": { 35 | "babel-eslint": "^9.0.0", 36 | "eslint": "^5.14.1", 37 | "eslint-config-airbnb": "^17.1.0", 38 | "eslint-config-prettier": "^4.1.0", 39 | "eslint-config-wesbos": "0.0.19", 40 | "eslint-plugin-html": "^5.0.3", 41 | "eslint-plugin-import": "^2.16.0", 42 | "eslint-plugin-jsx-a11y": "^6.2.1", 43 | "eslint-plugin-prettier": "^3.0.1", 44 | "eslint-plugin-react": "^7.12.4", 45 | "eslint-plugin-react-hooks": "^1.3.0", 46 | "prettier": "^1.16.4" 47 | }, 48 | "repository": { 49 | "type": "git", 50 | "url": "https://github.com/gatsbyjs/gatsby-starter-hello-world" 51 | }, 52 | "bugs": { 53 | "url": "https://github.com/gatsbyjs/gatsby/issues" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/components/BackBtn.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import styled from 'styled-components' 3 | 4 | const BackBtnStyle = styled.span` 5 | width: 100px; 6 | display: flex; 7 | align-items: center; 8 | color: #fff; 9 | text-decoration: none; 10 | font-size: 18px; 11 | font-weight: 600; 12 | 13 | &:hover svg { 14 | transform: translateX(-5px); 15 | } 16 | 17 | svg { 18 | transition: transform 0.3s cubic-bezier(0.165, 0.84, 0.44, 1); 19 | margin-right: 10px; 20 | } 21 | 22 | @media (max-width: 768px) { 23 | font-size: 16px; 24 | } 25 | ` 26 | 27 | const BackBtn = () => ( 28 | 29 | 40 | 41 | 42 | 43 | Back 44 | 45 | ) 46 | 47 | export default BackBtn 48 | -------------------------------------------------------------------------------- /src/components/Container.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | const Container = styled.div` 4 | max-width: 992px; 5 | width: 100%; 6 | margin: 0 auto; 7 | padding: 40px 15px; 8 | ` 9 | 10 | export default Container 11 | -------------------------------------------------------------------------------- /src/components/ContributeBtn.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import styled from 'styled-components' 3 | 4 | const ContributeBtnStyle = styled.a` 5 | position: absolute; 6 | top: 15px; 7 | right: 15px; 8 | width: 35px; 9 | height: 35px; 10 | border-radius: 50%; 11 | display: flex; 12 | justify-content: center; 13 | align-items: center; 14 | border: 1px solid #fff; 15 | cursor: pointer; 16 | 17 | &:hover { 18 | &:before { 19 | opacity: 1; 20 | visibility: visible; 21 | } 22 | } 23 | 24 | &:before { 25 | content: 'Contribute'; 26 | position: absolute; 27 | left: -115px; 28 | background-color: #fff; 29 | padding: 8px 12px; 30 | border-radius: 4px; 31 | color: #333; 32 | opacity: 0; 33 | visibility: hidden; 34 | transition: all 0.3s ease; 35 | } 36 | ` 37 | 38 | const ContributeBtn = ({ href }) => ( 39 | 40 | 50 | 51 | 52 | 53 | 54 | ) 55 | 56 | export default ContributeBtn 57 | -------------------------------------------------------------------------------- /src/components/Footer.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import styled from 'styled-components' 3 | 4 | const FooterWrapper = styled.footer` 5 | height: 100px; 6 | display: flex; 7 | justify-content: flex-end; 8 | align-items: center; 9 | flex-direction: column; 10 | ` 11 | 12 | const Copyright = styled.span` 13 | color: rgba(255, 255, 255, 0.6); 14 | ` 15 | 16 | const Footer = () => ( 17 | 18 | All screenshots © of their respective owners. 19 | 20 | ) 21 | 22 | export default Footer 23 | -------------------------------------------------------------------------------- /src/components/PortfolioItem.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | const PortfolioItem = styled.div` 4 | .portfolio-item { 5 | border-radius: 4px; 6 | overflow: hidden; 7 | } 8 | ` 9 | 10 | export default PortfolioItem 11 | -------------------------------------------------------------------------------- /src/components/PortfolioName.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | const PortfolioName = styled.h2` 4 | color: #fff; 5 | text-align: center; 6 | font-size: 3.4rem; 7 | margin-bottom: 0; 8 | ` 9 | 10 | export default PortfolioName 11 | -------------------------------------------------------------------------------- /src/components/PortfolioPage.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | const PortfolioPage = styled.div` 4 | a { 5 | display: block; 6 | margin: 0 auto; 7 | padding: 10px; 8 | background-image: linear-gradient(135deg, #667eea 0%, #764ba2 100%); 9 | color: #fff; 10 | font-weight: 600; 11 | font-size: 15px; 12 | text-decoration: none; 13 | border-radius: 4px; 14 | text-align: center; 15 | width: 170px; 16 | margin-bottom: 50px; 17 | transition: all 0.15s ease; 18 | 19 | @media (max-width: 768px) { 20 | width: 140px; 21 | padding: 8px; 22 | } 23 | 24 | &:hover { 25 | box-shadow: 0 7px 14px rgba(50, 50, 93, 0.1), 26 | 0 3px 6px rgba(0, 0, 0, 0.08); 27 | transform: translateY(-1px); 28 | } 29 | } 30 | 31 | video, 32 | img { 33 | border-radius: 4px; 34 | } 35 | ` 36 | 37 | export default PortfolioPage 38 | -------------------------------------------------------------------------------- /src/components/PortfoliosList.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | const PortfoliosList = styled.div` 4 | display: grid; 5 | grid-template-columns: repeat(2, 1fr); 6 | grid-gap: 40px 25px; 7 | width: 100%; 8 | 9 | @media (max-width: 768px) { 10 | grid-template-columns: 1fr; 11 | } 12 | 13 | a { 14 | text-decoration: none; 15 | 16 | &:hover { 17 | .portfolio-item__title:before { 18 | transform: scale(1); 19 | } 20 | } 21 | 22 | .portfolio-item__title { 23 | display: block; 24 | font-size: 22px; 25 | font-weight: 400; 26 | border-radius: 4px; 27 | margin-top: 10px; 28 | color: rgba(255, 255, 255, 0.9); 29 | position: relative; 30 | 31 | &:before { 32 | content: ''; 33 | width: 10px; 34 | height: 10px; 35 | border-radius: 50%; 36 | position: absolute; 37 | bottom: 8px; 38 | right: 0; 39 | background-color: rgba(255, 255, 255, 0.8); 40 | transform: scale(0); 41 | transform-origin: center; 42 | transition: transform 0.3s cubic-bezier(0.165, 0.84, 0.44, 1); 43 | } 44 | } 45 | } 46 | ` 47 | 48 | export default PortfoliosList 49 | -------------------------------------------------------------------------------- /src/components/SubTitle.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | const SubTitle = styled.h2` 4 | font-size: 3rem; 5 | margin-top: 6px; 6 | margin-bottom: 60px; 7 | color: rgba(255, 255, 255, 1); 8 | font-weight: 400; 9 | opacity: 0.8; 10 | 11 | span:nth-child(1) { 12 | color: #f093fb; 13 | } 14 | span:nth-child(2) { 15 | color: #f5576c; 16 | } 17 | ` 18 | 19 | export default SubTitle 20 | -------------------------------------------------------------------------------- /src/components/Title.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | const Title = styled.h1` 4 | display: block; 5 | background: linear-gradient(to right, #f093fb 0%, #f5576c 100%); 6 | -webkit-background-clip: text; 7 | -webkit-text-fill-color: transparent; 8 | font-size: 6.4rem; 9 | font-weight: 900; 10 | text-transform: lowercase; 11 | margin-bottom: 0; 12 | line-height: 1; 13 | margin-bottom: 20px; 14 | ` 15 | 16 | export default Title 17 | -------------------------------------------------------------------------------- /src/pages/404.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const NotFound = () =>

NOT FOUND 🙃

4 | 5 | export default NotFound 6 | -------------------------------------------------------------------------------- /src/pages/global.js: -------------------------------------------------------------------------------- 1 | import { createGlobalStyle } from 'styled-components' 2 | 3 | const GlobalStyle = createGlobalStyle` 4 | @import url('https://fonts.googleapis.com/css?family=Raleway:400,600,900&display=swap'); 5 | 6 | html, 7 | body { 8 | height: 100%; 9 | padding: 0; 10 | margin: 0; 11 | } 12 | 13 | html { 14 | box-sizing: border-box; 15 | font-size: 16px; 16 | } 17 | 18 | *, *:before, *:after { 19 | box-sizing: inherit; 20 | } 21 | 22 | body { 23 | font-family: 'Raleway', sans-serif; 24 | background-color: #0c0d17; 25 | -webkit-font-smoothing: antialiased; 26 | -moz-osx-font-smoothing: grayscale; 27 | } 28 | 29 | a { 30 | text-decoration: none; 31 | } 32 | 33 | p { 34 | line-height: 1.4; 35 | } 36 | 37 | /* Responsive */ 38 | @media (max-width: 768px) { 39 | html { font-size: 9px; } 40 | } 41 | 42 | .contribute-btn { 43 | position: absolute; 44 | right: 15px; 45 | top: 15px; 46 | color: #fff; 47 | text-decoration: none; 48 | text-transform: lowercase; 49 | } 50 | ` 51 | 52 | export default GlobalStyle 53 | -------------------------------------------------------------------------------- /src/pages/head.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Helmet } from 'react-helmet' 3 | 4 | const Head = () => ( 5 | 6 | 7 | Creative Portfolios 8 | 9 | ) 10 | 11 | export default Head 12 | -------------------------------------------------------------------------------- /src/pages/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable react-hooks/rules-of-hooks */ 2 | import React from 'react' 3 | import { Link, useStaticQuery, graphql } from 'gatsby' 4 | import Img from 'gatsby-image' 5 | import Tilt from 'react-parallax-tilt' 6 | 7 | import Head from './head' 8 | import GlobalStyle from './global' 9 | import PortfoliosList from '../components/PortfoliosList' 10 | import PortfolioItem from '../components/PortfolioItem' 11 | import ContributeBtn from '../components/ContributeBtn' 12 | import Container from '../components/Container' 13 | import SubTitle from '../components/SubTitle' 14 | import Footer from '../components/Footer' 15 | import Title from '../components/Title' 16 | 17 | const blog = () => { 18 | const data = useStaticQuery(graphql` 19 | { 20 | allMarkdownRemark(sort: { order: DESC, fields: [frontmatter___date] }) { 21 | edges { 22 | node { 23 | fields { 24 | slug 25 | } 26 | frontmatter { 27 | title 28 | image { 29 | childImageSharp { 30 | fluid(maxWidth: 800, maxHeight: 480, quality: 100) { 31 | ...GatsbyImageSharpFluid 32 | } 33 | } 34 | } 35 | } 36 | id 37 | } 38 | } 39 | } 40 | } 41 | `) 42 | 43 | return ( 44 | <> 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | Creative Portfolios 53 | 54 | 55 | Is a curation of the most creative portfolios made by{' '} 56 | designers & developers. 57 | 58 | 59 | 60 | {data.allMarkdownRemark.edges.map(edge => ( 61 | 62 | 63 | 72 | 75 | 76 | 77 | {edge.node.frontmatter.title} 78 | 79 | 80 | 81 | ))} 82 | 83 | 84 |