diff --git a/README.md b/README.md
index 8e286e2..48fcb32 100644
--- a/README.md
+++ b/README.md
@@ -13,3 +13,4 @@ It requires Node.js 22 or newer.
6. Run `npm test` to execute the unit tests.
7. When you are satisfied with the results run `npm run export` to generate the static site.
* The results of the export can be found in the `out` folder.
+
diff --git a/__tests__/index.test.jsx b/__tests__/index.test.jsx
index 1ce08cc..48fd099 100644
--- a/__tests__/index.test.jsx
+++ b/__tests__/index.test.jsx
@@ -18,13 +18,13 @@ describe('Home page', () => {
it('renders all entry types with links', () => {
const entries = [
- { url: 'https://github.com/u', title: 'GitHub', fa: 'fab fa-github', type: 'github' },
- { url: 'https://twitter.com/u', title: 'Twitter', fa: 'fab fa-twitter', type: 'twitter' },
- { url: 'https://www.linkedin.com/in/u', title: 'LinkedIn', fa: 'fab fa-linkedin-in', type: 'linkedin' },
- { url: 'mailto:u@example.com', title: 'Email u@example.com', fa: 'fas fa-at', type: 'email', target: '_self' },
- { url: 'https://bitbucket.org/u', title: 'Bitbucket', fa: 'fab fa-bitbucket', type: 'bitbucket' },
- { url: 'https://stackoverflow.com/users/1', title: 'Stack Overflow', fa: 'fab fa-stack-overflow', type: 'stack-overflow' },
- { url: 'https://stackexchange.com/users/1', title: 'Stack Exchange', fa: 'fab fa-stack-exchange', type: 'stack-exchange' }
+ { url: 'https://github.com/u', title: 'GitHub', type: 'github' },
+ { url: 'https://twitter.com/u', title: 'Twitter', type: 'twitter' },
+ { url: 'https://www.linkedin.com/in/u', title: 'LinkedIn', type: 'linkedin' },
+ { url: 'mailto:u@example.com', title: 'Email u@example.com', type: 'email', target: '_self' },
+ { url: 'https://bitbucket.org/u', title: 'Bitbucket', type: 'bitbucket' },
+ { url: 'https://stackoverflow.com/users/1', title: 'Stack Overflow', type: 'stack-overflow' },
+ { url: 'https://stackexchange.com/users/1', title: 'Stack Exchange', type: 'stack-exchange' }
];
render();
@@ -40,7 +40,7 @@ describe('Home page', () => {
});
it('renders div when entry has no URL', () => {
- const entry = { url: null, title: 'Twitter', fa: 'fab fa-twitter', type: 'twitter' };
+ const entry = { url: null, title: 'Twitter', type: 'twitter' };
const { container } = render();
const element = container.querySelector('.portfolio__element--twitter');
expect(element.tagName).toBe('DIV');
diff --git a/package-lock.json b/package-lock.json
index b306353..ad4b159 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,6 +9,10 @@
"version": "1.0.0",
"license": "MIT",
"dependencies": {
+ "@fortawesome/fontawesome-svg-core": "^6.5.2",
+ "@fortawesome/free-brands-svg-icons": "^6.5.2",
+ "@fortawesome/free-solid-svg-icons": "^6.5.2",
+ "@fortawesome/react-fontawesome": "^0.2.0",
"next": "15.3.3",
"react": "18.2.0",
"react-dom": "18.2.0"
@@ -669,6 +673,64 @@
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
+ "node_modules/@fortawesome/fontawesome-common-types": {
+ "version": "6.7.2",
+ "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.7.2.tgz",
+ "integrity": "sha512-Zs+YeHUC5fkt7Mg1l6XTniei3k4bwG/yo3iFUtZWd/pMx9g3fdvkSK9E0FOC+++phXOka78uJcYb8JaFkW52Xg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@fortawesome/fontawesome-svg-core": {
+ "version": "6.7.2",
+ "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.7.2.tgz",
+ "integrity": "sha512-yxtOBWDrdi5DD5o1pmVdq3WMCvnobT0LU6R8RyyVXPvFRd2o79/0NCuQoCjNTeZz9EzA9xS3JxNWfv54RIHFEA==",
+ "license": "MIT",
+ "dependencies": {
+ "@fortawesome/fontawesome-common-types": "6.7.2"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@fortawesome/free-brands-svg-icons": {
+ "version": "6.7.2",
+ "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.7.2.tgz",
+ "integrity": "sha512-zu0evbcRTgjKfrr77/2XX+bU+kuGfjm0LbajJHVIgBWNIDzrhpRxiCPNT8DW5AdmSsq7Mcf9D1bH0aSeSUSM+Q==",
+ "license": "(CC-BY-4.0 AND MIT)",
+ "dependencies": {
+ "@fortawesome/fontawesome-common-types": "6.7.2"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@fortawesome/free-solid-svg-icons": {
+ "version": "6.7.2",
+ "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.7.2.tgz",
+ "integrity": "sha512-GsBrnOzU8uj0LECDfD5zomZJIjrPhIlWU82AHwa2s40FKH+kcxQaBvBo3Z4TxyZHIyX8XTDxsyA33/Vx9eFuQA==",
+ "license": "(CC-BY-4.0 AND MIT)",
+ "dependencies": {
+ "@fortawesome/fontawesome-common-types": "6.7.2"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@fortawesome/react-fontawesome": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.2.tgz",
+ "integrity": "sha512-EnkrprPNqI6SXJl//m29hpaNzOp1bruISWaOiRtkMi/xSvHJlzc2j2JAYS7egxt/EbjSNV/k6Xy0AQI6vB2+1g==",
+ "license": "MIT",
+ "dependencies": {
+ "prop-types": "^15.8.1"
+ },
+ "peerDependencies": {
+ "@fortawesome/fontawesome-svg-core": "~1 || ~6",
+ "react": ">=16.3"
+ }
+ },
"node_modules/@humanwhocodes/config-array": {
"version": "0.11.14",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
@@ -7565,7 +7627,6 @@
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -8079,7 +8140,6 @@
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"loose-envify": "^1.4.0",
@@ -8091,7 +8151,6 @@
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
- "dev": true,
"license": "MIT"
},
"node_modules/psl": {
diff --git a/package.json b/package.json
index 18c22f0..e2497b5 100644
--- a/package.json
+++ b/package.json
@@ -15,7 +15,11 @@
"dependencies": {
"next": "15.3.3",
"react": "18.2.0",
- "react-dom": "18.2.0"
+ "react-dom": "18.2.0",
+ "@fortawesome/fontawesome-svg-core": "^6.5.2",
+ "@fortawesome/free-brands-svg-icons": "^6.5.2",
+ "@fortawesome/free-solid-svg-icons": "^6.5.2",
+ "@fortawesome/react-fontawesome": "^0.2.0"
},
"devDependencies": {
"@testing-library/jest-dom": "6.1.5",
diff --git a/pages/index.js b/pages/index.js
index 2c27419..4b0740b 100644
--- a/pages/index.js
+++ b/pages/index.js
@@ -1,5 +1,15 @@
import Head from 'next/head'
import Script from 'next/script'
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
+import {
+ faGithub,
+ faTwitter,
+ faLinkedinIn,
+ faBitbucket,
+ faStackOverflow,
+ faStackExchange,
+} from '@fortawesome/free-brands-svg-icons'
+import { faAt } from '@fortawesome/free-solid-svg-icons'
export async function getStaticProps() {
const fs = require('fs')
@@ -43,13 +53,13 @@ export async function getStaticProps() {
}
}
const p = data.portfolio || {}
- if (p.github) assign(p.github.order, { url: p.github.username ? `https://github.com/${p.github.username}` : null, title: 'GitHub', fa: 'fab fa-github', type: 'github' })
- if (p.twitter) assign(p.twitter.order, { url: p.twitter.handle ? `https://twitter.com/${p.twitter.handle}` : null, title: 'Twitter', fa: 'fab fa-twitter', type: 'twitter' })
- if (p.linkedIn) assign(p.linkedIn.order, { url: p.linkedIn.username ? `https://www.linkedin.com/in/${p.linkedIn.username}` : null, title: 'LinkedIn', fa: 'fab fa-linkedin-in', type: 'linkedin' })
- if (p.email) assign(p.email.order, { url: p.email.address ? `mailto:${p.email.address}` : null, title: `Email ${p.email.address || 'me'}`, fa: 'fas fa-at', type: 'email', target: '_self' })
- if (p.bitbucket) assign(p.bitbucket.order, { url: p.bitbucket.username ? `https://bitbucket.org/${p.bitbucket.username}` : null, title: 'Bitbucket', fa: 'fab fa-bitbucket', type: 'bitbucket' })
- if (p.stackOverflow) assign(p.stackOverflow.order, { url: p.stackOverflow.id ? `https://stackoverflow.com/users/${p.stackOverflow.id}` : null, title: 'Stack Overflow', fa: 'fab fa-stack-overflow', type: 'stack-overflow' })
- if (p.stackExchange) assign(p.stackExchange.order, { url: p.stackExchange.id ? `https://stackexchange.com/users/${p.stackExchange.id}` : null, title: 'Stack Exchange', fa: 'fab fa-stack-exchange', type: 'stack-exchange' })
+ if (p.github) assign(p.github.order, { url: p.github.username ? `https://github.com/${p.github.username}` : null, title: 'GitHub', type: 'github' })
+ if (p.twitter) assign(p.twitter.order, { url: p.twitter.handle ? `https://twitter.com/${p.twitter.handle}` : null, title: 'Twitter', type: 'twitter' })
+ if (p.linkedIn) assign(p.linkedIn.order, { url: p.linkedIn.username ? `https://www.linkedin.com/in/${p.linkedIn.username}` : null, title: 'LinkedIn', type: 'linkedin' })
+ if (p.email) assign(p.email.order, { url: p.email.address ? `mailto:${p.email.address}` : null, title: `Email ${p.email.address || 'me'}`, type: 'email', target: '_self' })
+ if (p.bitbucket) assign(p.bitbucket.order, { url: p.bitbucket.username ? `https://bitbucket.org/${p.bitbucket.username}` : null, title: 'Bitbucket', type: 'bitbucket' })
+ if (p.stackOverflow) assign(p.stackOverflow.order, { url: p.stackOverflow.id ? `https://stackoverflow.com/users/${p.stackOverflow.id}` : null, title: 'Stack Overflow', type: 'stack-overflow' })
+ if (p.stackExchange) assign(p.stackExchange.order, { url: p.stackExchange.id ? `https://stackexchange.com/users/${p.stackExchange.id}` : null, title: 'Stack Exchange', type: 'stack-exchange' })
const portfolioEntries = entries.filter(Boolean)
@@ -60,6 +70,16 @@ export async function getStaticProps() {
}
}
+const icons = {
+ github: faGithub,
+ twitter: faTwitter,
+ linkedin: faLinkedinIn,
+ email: faAt,
+ bitbucket: faBitbucket,
+ 'stack-overflow': faStackOverflow,
+ 'stack-exchange': faStackExchange,
+}
+
export default function Home({ data, headerPictureUrl, faviconUrl, faviconType, portfolioEntries, description }) {
return (
<>
@@ -69,7 +89,6 @@ export default function Home({ data, headerPictureUrl, faviconUrl, faviconType,
{faviconUrl && }
-
{data.googleAnalyticsID && (
<>
@@ -94,13 +113,13 @@ export default function Home({ data, headerPictureUrl, faviconUrl, faviconType,
entry.url ? (
-
+
) : (
)
diff --git a/styles/styles.css b/styles/styles.css
index 204971a..7835022 100644
--- a/styles/styles.css
+++ b/styles/styles.css
@@ -65,7 +65,7 @@ a:visited, a:hover {
border-radius: 50%;
text-align: center;
}
-.portfolio__element__icon > i {
+.portfolio__element__icon > svg {
font-size: 70px;
}
.portfolio__element:not(.portfolio__element--github):hover .portfolio__element__icon, .portfolio__element .portfolio__element:not(.portfolio__element--github):active .portfolio__element__icon {
@@ -81,7 +81,7 @@ a:visited, a:hover {
color: #dfdfdf;
background-color: initial;
}
-.portfolio__element--github .portfolio__element__icon i {
+.portfolio__element--github .portfolio__element__icon svg {
font-size: 128px;
}
.portfolio__element--github:hover .portfolio__element__icon, .portfolio__element--github .portfolio__element--github:active .portfolio__element__icon {