diff --git a/assets/images/travolta.gif b/assets/images/travolta.gif
new file mode 100644
index 0000000..9c34296
Binary files /dev/null and b/assets/images/travolta.gif differ
diff --git a/src/pages/404-page/index.hbs b/src/pages/404-page/index.hbs
new file mode 100644
index 0000000..1165f79
--- /dev/null
+++ b/src/pages/404-page/index.hbs
@@ -0,0 +1,21 @@
+
+
+
+ {{> ../../template-partials/meta pageTranslations=htmlWebpackPlugin.options.content.translations.about_us}}
+ {{> ../../template-partials/head}}
+
+
+ {{> ../../header/header }}
+
+
+ {{ lookup htmlWebpackPlugin.options.content.pageNotFound.title htmlWebpackPlugin.options.content.lang }}
+
+
+ {{ lookup htmlWebpackPlugin.options.content.pageNotFound.message htmlWebpackPlugin.options.content.lang }}
+
+
+
+
+ {{> ../../footer/footer}}
+
+
diff --git a/src/pages/404-page/index.js b/src/pages/404-page/index.js
new file mode 100644
index 0000000..16b8c6e
--- /dev/null
+++ b/src/pages/404-page/index.js
@@ -0,0 +1,2 @@
+('use strict');
+import './index.scss';
diff --git a/src/pages/404-page/index.scss b/src/pages/404-page/index.scss
new file mode 100644
index 0000000..e2f464a
--- /dev/null
+++ b/src/pages/404-page/index.scss
@@ -0,0 +1,27 @@
+@import '../../styles/constants';
+@import '../../styles/mixins';
+
+.page-not-found {
+ text-align: center;
+ padding: 64px 16px 0;
+
+ h1,
+ h2 {
+ margin: 15px 0;
+ line-height: 1.1;
+ }
+
+ h1 {
+ font-size: 1.5em;
+ }
+
+ h2 {
+ font-size: 1em;
+ }
+
+ img {
+ vertical-align: top;
+ max-width: 360px;
+ width: 100%;
+ }
+}
diff --git a/webpack.config.js b/webpack.config.js
index e069e11..8a24934 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -312,6 +312,19 @@ const mediaMentionsConfig = [
];
const BASE_URL = 'https://programming.org.ua';
+const pageNotFound = {
+ title: {
+ en: 'Four-zero-four',
+ uk: 'Чотири-нуль-чотири',
+ ru: 'Четыре-ноль-четыре',
+ },
+ message: {
+ en: 'You were looking for something we don’t have, or something that has been removed',
+ uk: 'Ви шукали те, чого в нас немає, або те, що було видалено',
+ ru: 'Вы искали то, чего у нас нет, или то, что было удалено',
+ },
+};
+
module.exports = async (_, { mode = 'development' }) => ({
entry: {
common: './src/common.js',
@@ -328,11 +341,13 @@ module.exports = async (_, { mode = 'development' }) => ({
'anketa/last/index': './src/pages/sign-up-success-page/index.js',
'email-confirmed/index': './src/pages/sign-up-confirmation-page/index.js',
'supportus/index': './src/pages/support-us-page/index.js',
+ '404/index': './src/pages/404-page/index.js',
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist'),
clean: true,
+ publicPath: '/',
},
plugins: [
new SitemapPlugin({
@@ -553,6 +568,17 @@ module.exports = async (_, { mode = 'development' }) => ({
),
},
}),
+ new HtmlWebpackPlugin({
+ template: 'src/pages/404-page/index.hbs',
+ chunks: ['common', '404/index'],
+ inject: 'body',
+ minify: mode === 'production',
+ filename: `${filenamePrefix}404.html`,
+ content: {
+ ...getCommonContent('/404/'),
+ pageNotFound,
+ },
+ }),
];
},
[]
@@ -606,6 +632,22 @@ module.exports = async (_, { mode = 'development' }) => ({
devServer: {
static: './dist',
hot: false,
+ historyApiFallback: {
+ rewrites: [
+ {
+ from: /^\/ru\/.*$/,
+ to: '/ru/404.html',
+ },
+ {
+ from: /^\/en\/.*$/,
+ to: '/en/404.html',
+ },
+ {
+ from: /^\/[^.]*$/,
+ to: '/404.html',
+ },
+ ],
+ },
},
}),
...(mode === 'production' && {