Skip to content

Commit

Permalink
feat: Add custom 404 page (#48)
Browse files Browse the repository at this point in the history
Created a custom 404 page to enhance user experience for non-existent routes.
  • Loading branch information
warnyul authored Nov 28, 2024
1 parent cfbcb19 commit c6f0e8b
Show file tree
Hide file tree
Showing 26 changed files with 166 additions and 47 deletions.
2 changes: 1 addition & 1 deletion firebase.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"rewrites": [
{
"source": "**",
"destination": "/index.html"
"destination": "/404.html"
}
],
"headers": [
Expand Down
File renamed without changes.
Binary file added src/assets/images/confused-robot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 2 additions & 0 deletions src/js/404.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import '../scss/404.scss';
import "./analytics.js";
22 changes: 22 additions & 0 deletions src/js/analytics.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { initializeApp } from "firebase/app";
import { getAnalytics, logEvent } from "firebase/analytics";

// See: https://firebase.google.com/docs/web/learn-more#config-object
const firebaseConfig = {
apiKey: "AIzaSyDJMVkse8Mla3rqrVak1qkfXYxlh2AmUd8",
authDomain: "bvarga-fe600.firebaseapp.com",
projectId: "bvarga-fe600",
storageBucket: "bvarga-fe600.appspot.com",
messagingSenderId: "443364341536",
appId: "1:443364341536:web:d7b91d4ecfa7618f594945",
measurementId: "G-PB70YSPDG1"
};

// Initialize Firebase
const app = initializeApp(firebaseConfig);

// Initialize Analytics and get a reference to the service
const analytics = getAnalytics(app);

// Export analytics
module.exports = analytics;
25 changes: 3 additions & 22 deletions src/js/index.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,5 @@
import '../scss/index.scss'

import { initializeApp } from "firebase/app";
import { getAnalytics, logEvent } from "firebase/analytics";

// See: https://firebase.google.com/docs/web/learn-more#config-object
const firebaseConfig = {
apiKey: "AIzaSyDJMVkse8Mla3rqrVak1qkfXYxlh2AmUd8",
authDomain: "bvarga-fe600.firebaseapp.com",
projectId: "bvarga-fe600",
storageBucket: "bvarga-fe600.appspot.com",
messagingSenderId: "443364341536",
appId: "1:443364341536:web:d7b91d4ecfa7618f594945",
measurementId: "G-PB70YSPDG1"
};

// Initialize Firebase
const app = initializeApp(firebaseConfig);

// Initialize Analytics and get a reference to the service
const analytics = getAnalytics(app);
import '../scss/index.scss';
import { analytics } from './analytics.js';

function trackButtonClick(obj) {
const event = obj.innerText || obj.textContent;
Expand All @@ -32,7 +13,7 @@ function trackSocialButtonClick(obj) {

function copyLink(url) {
window.navigator.clipboard.writeText(url);
confirm("Page URL copied to the clipboard.")
confirm("Page URL copied to the clipboard.");
}

// Attach Event Handlers
Expand Down
62 changes: 62 additions & 0 deletions src/scss/404.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
@import "poppins";
@import "variables";

// Reset
body, html {
margin: 0;
padding: 0;
font-family: $font-family;
background-color: $background-color;
color: $text-color;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}

// Main container
.error-container {
text-align: center;
max-width: 640px;
margin: auto;
padding: $gap;

header h1 {
font-size: $font-size-large;
margin-bottom: $gap;
color: $text-color;
}

header p {
font-size: $font-size-medium;
margin-bottom: $gap;
}

img {
width: 300px;
height: 270px;
margin-bottom: $gap;
filter: brightness(0) saturate(100%) invert(20%) sepia(97%) saturate(1590%) hue-rotate(193deg) brightness(95%) contrast(102%);
}

.action p {
font-size: $font-size-small;
margin-bottom: calc($gap / 2); // Smaller gap for less important text
}

.home-link {
display: inline-block;
padding: calc($gap / 2) $gap; // Padding with gap-based scaling
font-size: $font-size-link;
font-weight: bold;
color: $link-color;
background-color: $primary-color;
text-decoration: none;
border-radius: 5px;
transition: background-color 0.3s ease;

&:hover {
background-color: $hover-color;
}
}
}
8 changes: 4 additions & 4 deletions src/scss/_poppins.scss
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@
}

/* latin-ext */
@include font-face('Poppins', normal, 400, '../asset/resource/font/Poppins-Regular-latin-ext.woff2', 'U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF');
@include font-face('Poppins', normal, 400, '../assets/fonts/Poppins-Regular-latin-ext.woff2', 'U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF');

/* latin */
@include font-face('Poppins', normal, 400, '../asset/resource/font/Poppins-Regular-latin-ext.woff2', 'U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD');
@include font-face('Poppins', normal, 400, '../assets/fonts/Poppins-Regular-latin-ext.woff2', 'U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD');

/* latin-ext */
@include font-face('Poppins', normal, 700, '../asset/resource/font/Poppins-Bold-latin-ext.woff2', 'U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF');
@include font-face('Poppins', normal, 700, '../assets/fonts/Poppins-Bold-latin-ext.woff2', 'U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF');

/* latin */
@include font-face('Poppins', normal, 700, '../asset/resource/font/Poppins-Bold-latin-ext.woff2', 'U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD');
@include font-face('Poppins', normal, 700, '../assets/fonts/Poppins-Bold-latin-ext.woff2', 'U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD');
15 changes: 15 additions & 0 deletions src/scss/_variables.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
$font-family: 'Poppins', 'Arial', sans-serif;
$background-color: #D9E2EC;
$text-color: #00509E;
$primary-color: #4B5563;
$hover-color: #3CB371;
$link-color: #FFF;
$error-color: #f44336;
$border-radius: 4px;
$gap: 16px;
$button-padding: 24px;

$font-size-large: 48px; // Large font size for main heading
$font-size-medium: 24px; // Medium font size for subheading
$font-size-small: 16px; // Small font size for additional text
$font-size-link: 16px; // Font size for link text
21 changes: 5 additions & 16 deletions src/scss/index.scss
Original file line number Diff line number Diff line change
@@ -1,17 +1,6 @@
@use "poppins";
@use "fontawesome.scss";

$font-family: 'Poppins', 'Arial', sans-serif;
$background-color: #D9E2EC;
$text-color: #00509E;
$primary-color: #4B5563;
$hover-color: #3CB371;
$link-color: #FFF;
$border-radius: 4px;
$gap: 16px;
$header-font-size: 24px;
$button-padding: 24px;
$button-font-size: 16px;
@use "fontawesome";
@use "variables" as *;

// Reset
* {
Expand Down Expand Up @@ -69,7 +58,7 @@ header {
h1 {
color: $text-color;
margin: $gap 0px calc($gap * 0.75);
font-size: $header-font-size;
font-size: $font-size-medium;
line-height: 1;
font-weight: 700;
text-align: center;
Expand All @@ -86,7 +75,7 @@ h1 {
align-items: center;
justify-content: center;
text-decoration: none;
font-size: 16px;
font-size: $font-size-small;
line-height: 24px;
transition: background-color 0.3s ease;
}
Expand Down Expand Up @@ -127,7 +116,7 @@ footer {
justify-content: center;
margin-top: $gap;
width: 100%;
font-size: $button-font-size;
font-size: $font-size-small;
text-decoration: none;
text-align: center;
}
Expand Down
25 changes: 25 additions & 0 deletions src/views/404.ejs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>404 - Page not found - Oops!</title>
</head>
<body>
<div class="error-container">
<header>
<h1>Page not found</h1>
<p>Oops! Looks like you’ve hit a dead end.</p>
</header>
<picture>
<!-- Source of the image: https://www.cleanpng.com/png-http-404-error-user-interface-design-google-chrome-2045552/ -->
<source type="image/webp" srcset="../assets/images/confused-robot.png?as=webp">
<img src="../assets/images/confused-robot.png" alt="Confused robot looking for the page" width="300" height="270" />
</picture>
<div class="action">
<p>Don't worry, even robots get lost sometimes.</p>
<a href="/" class="home-link">Take Me Home</a>
</div>
</div>
</body>
</html>
6 changes: 3 additions & 3 deletions src/views/index.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@
<meta property="og:type" content="website" />
<meta property="og:title" content="Balázs Varga" />
<meta property="og:description" content="Discover the professional profile of Balázs Varga. View links to LinkedIn, GitHub, Bluesky, and blog content." />
<meta property="og:image" content="../asset/resource/profile.png" />
<meta property="og:image" content="../assets/images/profile.png" />
<meta property="og:image:alt" content="Balázs Varga's profile picture" />
</head>
<body>
<div class="clazz-container">
<div class="clazz-content">
<header>
<picture>
<source type="image/webp" srcset="../asset/resource/profile100w100h.png?as=webp" />
<img width="100" height="100" src="../asset/resource/profile100w100h.png" alt="Balázs Varga" class="clazz-profile-image" />
<source type="image/webp" srcset="../assets/images/profile100w100h.png?as=webp" />
<img width="100" height="100" src="../assets/images/profile100w100h.png" alt="Balázs Varga" class="clazz-profile-image" />
</picture>
<h1 class="clazz-text-center">Balázs Varga</h1>
</header>
Expand Down
25 changes: 24 additions & 1 deletion webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ module.exports = {
mode: "production",
entry: {
index: './src/js/index.js',
pageNotFound: './src/js/404.js',
},
output: {
path: outputDir,
Expand Down Expand Up @@ -76,7 +77,7 @@ module.exports = {
new CopyWebpackPlugin({
patterns: [
{
context: __dirname + "/src/asset/raw",
context: __dirname + "/src/assets/raw",
from: "**",
}
],
Expand All @@ -92,6 +93,7 @@ module.exports = {
new HtmlWebpackPlugin({
alwaysWriteToDisk: true,
scriptLoading: 'blocking',
chunks: ['index'],
template: htmlWebpackPluginTemplateCustomizer({
templatePath: 'src/views/index.ejs',
templateEjsLoaderOption: {
Expand Down Expand Up @@ -144,6 +146,27 @@ module.exports = {
minifyJS: true,
}
}),
new HtmlWebpackPlugin({
alwaysWriteToDisk: true,
scriptLoading: 'blocking',
chunks: ['pageNotFound'],
template: htmlWebpackPluginTemplateCustomizer({
templatePath: 'src/views/404.ejs',
templateEjsLoaderOption: {
data: {
},
}
}),
filename: '404.html',
inject: 'body',
hash: false,
minify: {
collapseWhitespace: true,
removeComments: true,
minifyCSS: true,
minifyJS: true,
}
}),
new MangleCssClassPlugin({
classNameRegExp: '(fa|clazz)-([a-zA-Z0-9-]+)',
reserveClassName: ['fa', 'fab'],
Expand Down

0 comments on commit c6f0e8b

Please sign in to comment.