mirror of
https://github.com/kremalicious/portfolio.git
synced 2025-02-01 12:29:36 +01:00
get most site metadata from the resume
This commit is contained in:
parent
b46b006dd7
commit
e84de746c7
52
README.md
52
README.md
@ -16,9 +16,9 @@
|
||||
|
||||
- [🎉 Features](#-features)
|
||||
- [⛵️ Lighthouse score](#️-lighthouse-score)
|
||||
- [🗂 JSON Resume](#-json-resume)
|
||||
- [💍 One data file to rule all pages](#-one-data-file-to-rule-all-pages)
|
||||
- [🐱 GitHub repositories](#-github-repositories)
|
||||
- 🗂 JSON Resume](#-json-resume)
|
||||
- [💅 Theme switcher](#-theme-switcher)
|
||||
- [🏆 SEO component](#-seo-component)
|
||||
- [📇 Client-side vCard creation](#-client-side-vcard-creation)
|
||||
@ -38,37 +38,17 @@
|
||||
|
||||
## 🎉 Features
|
||||
|
||||
The whole [portfolio](https://matthiaskretschmann.com) is a React-based Single Page App built with [Gatsby v2](https://www.gatsbyjs.org).
|
||||
The whole [portfolio](https://matthiaskretschmann.com) is a React-based single page app built with [Gatsby v2](https://www.gatsbyjs.org).
|
||||
|
||||
Most metadata is powered by one `resume.json` file based on [🗂 JSON Resume](#-json-resume), and one `projects.yml` file to [define the displayed projects](#-one-data-file-to-rule-all-pages).
|
||||
|
||||
### ⛵️ Lighthouse score
|
||||
|
||||
![Lighthouse scores](https://lighthouse.now.sh/?perf=100&pwa=100&a11y=100&bp=100&seo=100)
|
||||
|
||||
### 💍 One data file to rule all pages
|
||||
|
||||
All content is powered by one YAML file where all the portfolio's projects are defined. The project description itself is transformed from Markdown written inside the YAML file into HTML on build time.
|
||||
|
||||
Gatsby automatically creates pages from each item in that file utilizing the [`Project.jsx`](src/templates/Project.jsx) template.
|
||||
|
||||
- [`gatsby-node.js`](gatsby-node.js)
|
||||
- [`content/projects.yml`](content/projects.yml)
|
||||
- [`src/templates/Project.jsx`](src/templates/Project.jsx)
|
||||
|
||||
### 🐱 GitHub repositories
|
||||
|
||||
The open source section at the bottom of the front page shows selected GitHub repositories, sourced from GitHub.
|
||||
|
||||
On build time, all my public repositories are fetched from GitHub, then filtered against the ones defined in `content/repos.yml`, sorted by the last push date, and provided via the page context of the front page.
|
||||
|
||||
If you want to know how, have a look at the respective components:
|
||||
|
||||
- [`gatsby-node.js`](gatsby-node.js)
|
||||
- [`content/repos.yml`](content/repos.yml)
|
||||
- [`src/components/molecules/Repository.jsx`](src/components/molecules/Repository.jsx)
|
||||
|
||||
### 🗂 JSON Resume
|
||||
|
||||
Resume page based on [JSON Resume](https://jsonresume.org) standard. Most site metadata and social profiles are defined in [`content/resume.json`](content/resume.json) and used throughout the site.
|
||||
Most site metadata and social profiles are defined in [`content/resume.json`](content/resume.json) based on the [JSON Resume](https://jsonresume.org) standard and used throughout the site as a custom React hook. Additionally, a resume page is created under `/resume`.
|
||||
|
||||
If you want to know how, have a look at the respective components:
|
||||
|
||||
@ -76,6 +56,28 @@ If you want to know how, have a look at the respective components:
|
||||
- [`src/pages/resume/index.jsx`](src/pages/resume/index.jsx)
|
||||
- [`src/hooks/use-resume.js`](src/hooks/use-resume.js)
|
||||
|
||||
### 💍 One data file to rule all pages
|
||||
|
||||
All displayed project content is powered by one YAML file where all the portfolio's projects are defined. The project description itself is transformed from Markdown written inside the YAML file into HTML on build time.
|
||||
|
||||
Gatsby automatically creates pages from each item in that file utilizing the [`Project.jsx`](src/templates/Project.jsx) template.
|
||||
|
||||
- [`content/projects.yml`](content/projects.yml)
|
||||
- [`gatsby-node.js`](gatsby-node.js)
|
||||
- [`src/templates/Project.jsx`](src/templates/Project.jsx)
|
||||
|
||||
### 🐱 GitHub repositories
|
||||
|
||||
The open source section at the bottom of the front page shows selected GitHub repositories, sourced from GitHub.
|
||||
|
||||
On build time, all my public repositories are fetched from GitHub, then filtered against the ones defined in `content/repos.yml`, sorted by the last push date, and provided via the `pageContext` of the front page.
|
||||
|
||||
If you want to know how, have a look at the respective components:
|
||||
|
||||
- [`gatsby-node.js`](gatsby-node.js)
|
||||
- [`content/repos.yml`](content/repos.yml)
|
||||
- [`src/components/molecules/Repository.jsx`](src/components/molecules/Repository.jsx)
|
||||
|
||||
### 💅 Theme switcher
|
||||
|
||||
Includes a theme switcher which allows user to toggle between a light and a dark theme. Switching between them also happens automatically based on user's local sunset and sunrise times. Uses Cloudflare's geo location HTTP header functionality.
|
||||
|
@ -1,9 +1,6 @@
|
||||
# more personal metadata can be found in ./resume.json
|
||||
# most personal metadata can be found in ./resume.json
|
||||
|
||||
- title: Matthias Kretschmann
|
||||
tagline: Designer & Developer
|
||||
description: Portfolio of web & ui designer/developer hybrid Matthias Kretschmann.
|
||||
url: https://matthiaskretschmann.com
|
||||
- description: Portfolio of web & ui designer/developer hybrid Matthias Kretschmann.
|
||||
img: ../src/images/twitter-card.png
|
||||
|
||||
availability:
|
||||
|
@ -2,13 +2,15 @@ const path = require('path')
|
||||
const fs = require('fs')
|
||||
const yaml = require('js-yaml')
|
||||
const meta = yaml.load(fs.readFileSync('./content/meta.yml', 'utf8'))
|
||||
const { title, url, matomoSite, matomoUrl } = meta[0]
|
||||
const resume = require('./content/resume.json')
|
||||
const { matomoSite, matomoUrl } = meta[0]
|
||||
const { name, website } = resume.basics
|
||||
|
||||
require('dotenv').config()
|
||||
|
||||
module.exports = {
|
||||
siteMetadata: {
|
||||
siteUrl: `${url}`
|
||||
siteUrl: `${website}`
|
||||
},
|
||||
plugins: [
|
||||
'gatsby-transformer-yaml',
|
||||
@ -50,7 +52,7 @@ module.exports = {
|
||||
resolve: 'gatsby-plugin-matomo',
|
||||
options: {
|
||||
siteId: `${matomoSite}`,
|
||||
siteUrl: `${url}`,
|
||||
siteUrl: `${website}`,
|
||||
matomoUrl: `${matomoUrl}`,
|
||||
localScript: '/piwik.js'
|
||||
}
|
||||
@ -58,7 +60,7 @@ module.exports = {
|
||||
{
|
||||
resolve: 'gatsby-plugin-manifest',
|
||||
options: {
|
||||
name: title.toLowerCase(),
|
||||
name: name.toLowerCase(),
|
||||
short_name: 'mk',
|
||||
start_url: '/',
|
||||
background_color: '#e7eef4',
|
||||
|
6
package-lock.json
generated
6
package-lock.json
generated
@ -12308,9 +12308,9 @@
|
||||
"integrity": "sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ=="
|
||||
},
|
||||
"handlebars": {
|
||||
"version": "4.5.2",
|
||||
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.2.tgz",
|
||||
"integrity": "sha512-29Zxv/cynYB7mkT1rVWQnV7mGX6v7H/miQ6dbEpYTKq5eJBN7PsRB+ViYJlcT6JINTSu4dVB9kOqEun78h6Exg==",
|
||||
"version": "4.5.3",
|
||||
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.3.tgz",
|
||||
"integrity": "sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"neo-async": "^2.6.0",
|
||||
|
@ -5,36 +5,36 @@ import { useMeta } from '../../hooks/use-meta'
|
||||
import { useResume } from '../../hooks/use-resume'
|
||||
|
||||
const MetaTags = ({ title, description, url, image, meta }) => {
|
||||
const resume = useResume()
|
||||
const twitterHandle = resume.basics.profiles.filter(
|
||||
const { basics } = useResume()
|
||||
const twitterHandle = basics.profiles.filter(
|
||||
({ network }) => network === 'Twitter'
|
||||
)[0].username
|
||||
|
||||
return (
|
||||
<Helmet
|
||||
defaultTitle={`${meta.title.toLowerCase()} { ${meta.tagline.toLowerCase()} }`}
|
||||
titleTemplate={`%s // ${meta.title.toLowerCase()} { ${meta.tagline.toLowerCase()} }`}
|
||||
defaultTitle={`${basics.name.toLowerCase()} { ${basics.label.toLowerCase()} }`}
|
||||
titleTemplate={`%s // ${basics.name.toLowerCase()} { ${basics.label.toLowerCase()} }`}
|
||||
title={title}
|
||||
>
|
||||
<html lang="en" />
|
||||
|
||||
{/* General tags */}
|
||||
<meta name="description" content={description} />
|
||||
<meta name="image" content={`${meta.url}${image}`} />
|
||||
<meta name="image" content={`${basics.website}${image}`} />
|
||||
<link rel="canonical" href={url} />
|
||||
|
||||
{/* OpenGraph tags */}
|
||||
<meta property="og:url" content={url} />
|
||||
<meta property="og:title" content={title} />
|
||||
<meta property="og:description" content={description} />
|
||||
<meta property="og:image" content={`${meta.url}${image}`} />
|
||||
<meta property="og:image" content={`${basics.website}${image}`} />
|
||||
|
||||
{/* Twitter Card tags */}
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:creator" content={twitterHandle} />
|
||||
<meta name="twitter:title" content={title} />
|
||||
<meta name="twitter:description" content={description} />
|
||||
<meta name="twitter:image" content={`${meta.url}${image}`} />
|
||||
<meta name="twitter:image" content={`${basics.website}${image}`} />
|
||||
</Helmet>
|
||||
)
|
||||
}
|
||||
@ -53,12 +53,13 @@ SEO.propTypes = {
|
||||
|
||||
export default function SEO({ project }) {
|
||||
const meta = useMeta()
|
||||
const { basics } = useResume()
|
||||
const title = (project && project.title) || null
|
||||
const description = (project && project.fields.excerpt) || meta.description
|
||||
const image =
|
||||
(project && project.img.childImageSharp.twitterImage.src) ||
|
||||
meta.img.childImageSharp.resize.src
|
||||
const url = (project && `${meta.url}${project.slug}`) || meta.url
|
||||
const url = (project && `${basics.website}${project.slug}`) || basics.website
|
||||
|
||||
return (
|
||||
<MetaTags
|
||||
|
@ -2,10 +2,10 @@ import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Link } from 'gatsby'
|
||||
import posed from 'react-pose'
|
||||
import { useMeta } from '../../hooks/use-meta'
|
||||
import { moveInBottom } from '../atoms/Transitions'
|
||||
import { ReactComponent as Logo } from '../../images/logo.svg'
|
||||
import styles from './LogoUnit.module.scss'
|
||||
import { useResume } from '../../hooks/use-resume'
|
||||
|
||||
LogoUnit.propTypes = {
|
||||
minimal: PropTypes.bool,
|
||||
@ -13,16 +13,18 @@ LogoUnit.propTypes = {
|
||||
}
|
||||
|
||||
export default function LogoUnit({ minimal }) {
|
||||
const { title, tagline } = useMeta()
|
||||
const { basics } = useResume()
|
||||
const Animation = posed.div(moveInBottom)
|
||||
|
||||
return (
|
||||
<Animation>
|
||||
<Link className={minimal ? styles.minimal : styles.logounit} to={'/'}>
|
||||
<Logo className={styles.logo} />
|
||||
<h1 className={`p-name ${styles.title}`}>{title.toLowerCase()}</h1>
|
||||
<h1 className={`p-name ${styles.title}`}>
|
||||
{basics.name.toLowerCase()}
|
||||
</h1>
|
||||
<p className={`p-job-title ${styles.description}`}>
|
||||
{tagline.toLowerCase()}
|
||||
{basics.label.toLowerCase()}
|
||||
</p>
|
||||
</Link>
|
||||
</Animation>
|
||||
|
@ -3,10 +3,7 @@ import { useStaticQuery, graphql } from 'gatsby'
|
||||
const query = graphql`
|
||||
query Meta {
|
||||
metaYaml {
|
||||
title
|
||||
tagline
|
||||
description
|
||||
url
|
||||
img {
|
||||
childImageSharp {
|
||||
resize(width: 980) {
|
||||
|
Loading…
Reference in New Issue
Block a user