diff --git a/src/404/404.sass b/src/404/404.sass
new file mode 100644
index 0000000..e87d358
--- /dev/null
+++ b/src/404/404.sass
@@ -0,0 +1,52 @@
+@use "../about/about"
+
+
+.not-found
+ background: about.$reader-bg
+ display: flex
+ flex-direction: column
+ flex-grow: 1
+ justify-content: center
+ align-items: center
+ h1,h2,h3,h4
+ font-family: Neuton, serif
+
+.nf-ctr
+ display: flex
+ flex-direction: column
+
+ h1,h2,h3,p
+ text-align: center
+ margin: 0
+
+.nf-title
+ background: white
+ color: black
+ border-radius: 15px 15px 0 0
+ padding: 15px
+ display: flex
+ flex-direction: column
+ h1
+ margin: 10px 0
+ font-size: 100px
+ h3
+ font-size: 30px
+ margin-bottom: 10px
+
+.nf-desc
+ background: black
+ color: white
+ padding: 15px
+ border-radius: 0 0 15px 15px
+
+.routes-list
+ padding: 15px
+ display: flex
+ flex-direction: row
+ flex-wrap: wrap
+ gap: 15px
+ justify-content: center
+ align-items: center
+ a
+ font-size: 20px
+ text-decoration: underline
diff --git a/src/404/NotFound.tsx b/src/404/NotFound.tsx
new file mode 100644
index 0000000..0c363d7
--- /dev/null
+++ b/src/404/NotFound.tsx
@@ -0,0 +1,35 @@
+import "./404.sass";
+import { ROUTES } from "../router/Route";
+import { Link } from "../router/Link";
+import { motion } from "motion/react";
+import { AnimateSpin, AnimateFade } from "../animations";
+import { type Path } from "../router/router";
+
+export default function NotFoundPage() {
+ return
+
+
+
404
+ This page was not found
+
+
+
Did you mistype the URL? Here are a list of common links
+
+ {
+ ROUTES.map(
+ ([path,name]) =>
+ )
+ }
+
+
+
+
+}
+
+function LinkBox({path, name}: {path: Path, name: string}) {
+ return (
+
+ {name}
+
+ );
+}
diff --git a/src/articles/reader.sass b/src/articles/reader.sass
index 155f084..33fb11f 100644
--- a/src/articles/reader.sass
+++ b/src/articles/reader.sass
@@ -63,4 +63,4 @@
font-weight: bold
color: red !important
background: white
- border-radius: 999px
\ No newline at end of file
+ border-radius: 999px
diff --git a/src/index.sass b/src/index.sass
index 6ef9740..ea1e1d2 100644
--- a/src/index.sass
+++ b/src/index.sass
@@ -26,4 +26,4 @@ button
border: none
padding: 0
color: white
- cursor: pointer
\ No newline at end of file
+ cursor: pointer
diff --git a/src/index/canvas.sass b/src/index/canvas.sass
index 30f4794..feea2bd 100644
--- a/src/index/canvas.sass
+++ b/src/index/canvas.sass
@@ -20,4 +20,4 @@
align-self: flex-end
position: fixed
bottom: 0
- right: 15px
\ No newline at end of file
+ right: 15px
diff --git a/src/links/links.sass b/src/links/links.sass
index 2242b00..23c37d1 100644
--- a/src/links/links.sass
+++ b/src/links/links.sass
@@ -47,7 +47,6 @@
border-radius: 0 15px 0 0
padding: 10px
font-weight: bold
- font-family: Neuton, serif
border-bottom: white 2px solid
h2
margin: 0
@@ -55,9 +54,11 @@
.link-desc
background: black
color: white
- font-family: Inter, sans-serif
- padding: 10px
+ padding: 15px
flex-grow: 1
justify-content: center
align-items: center
border-radius: 0 0 15px 0
+
+ font-family: Neuton, serif
+ font-size: 20px
diff --git a/src/router/Route.tsx b/src/router/Route.tsx
index 1d4f2cb..fbe07d1 100644
--- a/src/router/Route.tsx
+++ b/src/router/Route.tsx
@@ -1,8 +1,8 @@
-import React, {PropsWithChildren} from "react";
+import React, {type PropsWithChildren, ReactElement} from "react";
import {useRouter} from "./RouterContext";
import {Path} from "./router";
-type Route = [Path, string];
+export type Route = [Path, string];
type Routes = [Route, Route, Route, Route];
export const ROUTES: Routes = [
["/", "Home"],
@@ -11,7 +11,8 @@ export const ROUTES: Routes = [
["/links", "Links"]
];
-function Route(props: PropsWithChildren & {route: Route}) {
+type RouteProps = PropsWithChildren & {route: Route};
+function Route(props: RouteProps) {
const {route: [path], children} = props;
const router = useRouter();
// remove search params
@@ -25,22 +26,38 @@ const Canvas = React.lazy(() => import("../index/Canvas"));
const About = React.lazy(() => import("../about/AboutPage"));
const ArticlesList = React.lazy(() => import("../articles/ArticlesList"));
const LinkTree = React.lazy(() => import("../links/LinkTree"));
+const NotFound = React.lazy(() => import("../404/NotFound"));
+
+// ensures only one route is rendered at a time, with a virtual 404 page as fallback
+function RouteSwitch({children}: {children: ReactElement[]}) {
+ const router = useRouter();
+
+ const child = children.find(child => {
+ const [expected] = child.props.route;
+ const [current] = /\/?\w*[^?]/.exec(router.current) ?? [location.pathname];
+ return current === expected
+ });
+
+ return <>{child || }>
+}
export function Routes() {
const [index, about, articles, links] = ROUTES;
return <>
-
-
-
-
-
-
-
-
-
-
-
-
- >
-}
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+}