aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorKevin Hoerr <kjhoerr@protonmail.com>2023-12-23 23:59:02 -0500
committerGitHub <noreply@github.com>2023-12-23 23:59:02 -0500
commit3140267ea0a3b37032003992695afd7dc1f4f46c (patch)
tree8fa8dc00f62bcaaa0c5cfac3cec199c45dd5f29c /src
parent23cc0d2f06958720b694660cd8c7e4125d09b231 (diff)
downloadsubmelon.dev-3140267ea0a3b37032003992695afd7dc1f4f46c.tar.gz
submelon.dev-3140267ea0a3b37032003992695afd7dc1f4f46c.tar.bz2
submelon.dev-3140267ea0a3b37032003992695afd7dc1f4f46c.zip
De gatsby (#326)
* de-gatsby * Add inversed image for dark background * eleventy * Reinstate workflows to prior state * Strip inline styling for index image * Passthrough src/public/ files * Use global data to encode build date encoded string * Clean public directory before build * Reinstall eslint, prettier * Reinstate .gitattributes for public dir * build.yml: escape config file for version numbering * Revert public changes for PR validation * Rename src/public/ to src/static/ * Include github-actions in dependabot updates * re-establish typescript * Update prevent-file-change-action to v1.5.1 * Re-add typescript to linting * Re-add typescript for eslint * Fix whitespace diff for tsconfig.json * Fix whitespace in .eslintrc.json
Diffstat (limited to 'src')
-rw-r--r--src/components/BlockLink.tsx17
-rw-r--r--src/components/Layout.tsx35
-rw-r--r--src/components/SEO.tsx17
-rw-r--r--src/components/index.ts4
-rw-r--r--src/config.ts23
-rw-r--r--src/hooks/SiteMetadata.ts21
-rw-r--r--src/hooks/SiteVersion.ts19
-rw-r--r--src/hooks/index.ts4
-rw-r--r--src/pages/404.njk10
-rw-r--r--src/pages/404.tsx23
-rw-r--r--src/pages/index.njk33
-rw-r--r--src/pages/index.tsx73
-rw-r--r--src/static/favicon-32x32.pngbin0 -> 3058 bytes
-rw-r--r--src/static/icons/code.svg4
-rw-r--r--src/static/icons/github.svg4
-rw-r--r--src/static/icons/icon-144x144.pngbin0 -> 42763 bytes
-rw-r--r--src/static/icons/icon-192x192.pngbin0 -> 72918 bytes
-rw-r--r--src/static/icons/icon-256x256.pngbin0 -> 122738 bytes
-rw-r--r--src/static/icons/icon-384x384.pngbin0 -> 252395 bytes
-rw-r--r--src/static/icons/icon-48x48.pngbin0 -> 6080 bytes
-rw-r--r--src/static/icons/icon-512x512.pngbin0 -> 414864 bytes
-rw-r--r--src/static/icons/icon-72x72.pngbin0 -> 11641 bytes
-rw-r--r--src/static/icons/icon-96x96.pngbin0 -> 20144 bytes
-rw-r--r--src/static/icons/mastodon.svg4
-rw-r--r--src/static/manifest.webmanifest34
-rw-r--r--src/static/static/81e0da73927123f3f6b0c9a2d0750e76/6cac9/main.webpbin0 -> 13260 bytes
-rw-r--r--src/static/static/81e0da73927123f3f6b0c9a2d0750e76/88e48/main.pngbin0 -> 43389 bytes
-rw-r--r--src/static/styles.css205
-rw-r--r--src/styles/BlockAnchor.ts21
-rw-r--r--src/styles/BlockBody.ts27
-rw-r--r--src/styles/BlockHeader.ts12
-rw-r--r--src/styles/Content.ts8
-rw-r--r--src/styles/Footer.ts13
-rw-r--r--src/styles/index.ts9
-rw-r--r--src/styles/main.css41
-rw-r--r--src/templates/layouts/page.njk37
36 files changed, 354 insertions, 344 deletions
diff --git a/src/components/BlockLink.tsx b/src/components/BlockLink.tsx
deleted file mode 100644
index 6b841f0..0000000
--- a/src/components/BlockLink.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-import React from "react";
-import { BlockAnchor, BlockBody } from "../styles";
-
-type BlockLinkProps = {
- children?: React.ReactNode;
- as?: undefined;
-} & React.LinkHTMLAttributes<HTMLAnchorElement>;
-
-const BlockLink = ({ children, ...attributes }: BlockLinkProps) => {
- return (
- <BlockBody theme={{ link: true }}>
- <BlockAnchor {...attributes}>{children}</BlockAnchor>
- </BlockBody>
- );
-};
-
-export default BlockLink;
diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx
deleted file mode 100644
index fec336f..0000000
--- a/src/components/Layout.tsx
+++ /dev/null
@@ -1,35 +0,0 @@
-import React from "react";
-import { IconContext } from "react-icons/lib";
-import { Content, Footer } from "../styles";
-import { useSiteVersion } from "../hooks";
-import { getTimestamp } from "../util/timestamp";
-
-import "../styles/main.css";
-
-interface LayoutProps {
- children: React.ReactNode;
-}
-
-const Layout = ({ children }: LayoutProps) => {
- const version = useSiteVersion();
- return (
- <React.StrictMode>
- <main>
- <IconContext.Provider
- value={{ size: "20", style: { marginBottom: "-4px" } }}
- >
- <Content>{children}</Content>
-
- <Footer>
- <span>
- &copy;2023 kjhoerr@https://submelon.dev/:
- {getTimestamp(Number(version))}
- </span>
- </Footer>
- </IconContext.Provider>
- </main>
- </React.StrictMode>
- );
-};
-
-export default Layout;
diff --git a/src/components/SEO.tsx b/src/components/SEO.tsx
deleted file mode 100644
index b13dc19..0000000
--- a/src/components/SEO.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-import React from "react";
-import { useSiteMetadata } from "../hooks";
-
-export function Head(): React.ReactElement {
- const { author, description, title } = useSiteMetadata();
-
- return (
- <>
- <meta name="twitter:description" content={description ?? ""} />
- <meta name="twitter:title" content={title ?? ""} />
- <meta name="twitter:creator" content={author ?? ""} />
- <meta name="twitter:card" content="summary" />
- <meta name="description" content={description ?? ""} />
- <title>{title}</title>
- </>
- );
-}
diff --git a/src/components/index.ts b/src/components/index.ts
deleted file mode 100644
index 6e7bcb7..0000000
--- a/src/components/index.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-import BlockLink from "./BlockLink";
-import Layout from "./Layout";
-
-export { BlockLink, Layout };
diff --git a/src/config.ts b/src/config.ts
new file mode 100644
index 0000000..3fdcf24
--- /dev/null
+++ b/src/config.ts
@@ -0,0 +1,23 @@
+import { getTimestamp } from "./util/timestamp";
+import BuildInfo from "../config.json";
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export default function (eleventyConfig: any) {
+ eleventyConfig.addPassthroughCopy({
+ "./src/static/": "/",
+ });
+ eleventyConfig.addGlobalData("buildTimeEncoded", () => {
+ return getTimestamp(Number(BuildInfo.version));
+ });
+ eleventyConfig.addWatchTarget("./src/config.ts");
+
+ return {
+ templateFormats: ["njk", "html"],
+ htmlTemplateEngine: "njk",
+ dir: {
+ input: "src/pages",
+ includes: "../templates",
+ output: "public",
+ },
+ };
+}
diff --git a/src/hooks/SiteMetadata.ts b/src/hooks/SiteMetadata.ts
deleted file mode 100644
index 889f42b..0000000
--- a/src/hooks/SiteMetadata.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { useStaticQuery, graphql } from "gatsby";
-
-type SiteMetadata = NonNullable<
- NonNullable<Queries.getSiteMetadataQuery["site"]>["siteMetadata"]
->;
-
-export const useSiteMetadata = (): SiteMetadata => {
- const { site } = useStaticQuery<Queries.getSiteMetadataQuery>(graphql`
- query getSiteMetadata {
- site {
- siteMetadata {
- author
- description
- title
- }
- }
- }
- `);
-
- return site?.siteMetadata ?? ({} as SiteMetadata);
-};
diff --git a/src/hooks/SiteVersion.ts b/src/hooks/SiteVersion.ts
deleted file mode 100644
index 6726a3c..0000000
--- a/src/hooks/SiteVersion.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import { useStaticQuery, graphql } from "gatsby";
-
-type SiteVersion = NonNullable<
- NonNullable<Queries.getSiteVersionQuery["site"]>["siteMetadata"]
->["version"];
-
-export const useSiteVersion = (): SiteVersion => {
- const { site } = useStaticQuery<Queries.getSiteVersionQuery>(graphql`
- query getSiteVersion {
- site {
- siteMetadata {
- version
- }
- }
- }
- `);
-
- return site?.siteMetadata?.version ?? "0";
-};
diff --git a/src/hooks/index.ts b/src/hooks/index.ts
deleted file mode 100644
index 1250d57..0000000
--- a/src/hooks/index.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-import { useSiteMetadata } from "./SiteMetadata";
-import { useSiteVersion } from "./SiteVersion";
-
-export { useSiteMetadata, useSiteVersion };
diff --git a/src/pages/404.njk b/src/pages/404.njk
new file mode 100644
index 0000000..3c965ac
--- /dev/null
+++ b/src/pages/404.njk
@@ -0,0 +1,10 @@
+---
+layout: layouts/page.njk
+---
+<section><h1>Not found</h1></section>
+<section>
+ Sorry! We couldn&apos;t find what you were looking for&nbsp;<span role="img" aria-label="Pensive emoji">😔</span>
+</section>
+<section>
+ <a href="/" aria-label="Return to the front page">Home</a>
+</section> \ No newline at end of file
diff --git a/src/pages/404.tsx b/src/pages/404.tsx
deleted file mode 100644
index 782a349..0000000
--- a/src/pages/404.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-import React from "react";
-import { BlockLink, Layout } from "../components";
-import { BlockBody, BlockHeader } from "../styles";
-
-const NotFoundPage = (): React.ReactElement => {
- return (
- <Layout>
- <BlockHeader>Not found</BlockHeader>
- <BlockBody>
- Sorry! We couldn&apos;t find what you were looking for
- <span role="img" aria-label="Pensive emoji">
- 😔
- </span>
- </BlockBody>
- <BlockLink href="/" aria-label="Return to the front page">
- Home
- </BlockLink>
- </Layout>
- );
-};
-
-export default NotFoundPage;
-export { Head } from "../components/SEO";
diff --git a/src/pages/index.njk b/src/pages/index.njk
new file mode 100644
index 0000000..67d8506
--- /dev/null
+++ b/src/pages/index.njk
@@ -0,0 +1,33 @@
+---
+layout: layouts/page.njk
+---
+<picture>
+ <source type="image/webp" srcSet="static/81e0da73927123f3f6b0c9a2d0750e76/6cac9/main.webp 350w" sizes="350px"/>
+ <img sizes="350px" loading="lazy" src="static/81e0da73927123f3f6b0c9a2d0750e76/88e48/main.png" alt="Picture of Kevin Hoerr"/>
+</picture>
+<section><h1>Hello!</h1></section>
+<section>
+ <p>I&apos;m a computer science and math graduate from Millersville University. I work as a Solutions Architect and specialize in development operations and systems validation for web applications.</p>
+ <p>During my time at Millersville I was the lead Linux admin for the Cyber Defense Organization (CDO). In addition to constructing a new computer lab for our efforts, we participated in NCL and MACCDC.</p>
+ <p>Most of my development experience is focused around full stack development. For the front-end I use TypeScript and ReactJS using create-react-app or NextJS. For back-end systems I have used both Java with Spring Boot and rust with actix-web extensively. To mediate APIs I have used Apache Kafka, OpenAPI, and GraphQL.</p>
+ <p>My free time is spent engaging in general computing hobbies. When I&apos;m not trying out new application frameworks, I am fiddling around with Guix or NixOS. I run a kubernetes cluster at home to manage, maintain, and secure my personal network as well as experimenting with distributed workloads.</p>
+ <em>- Kevin H.</em>
+</section>
+<section>
+ <a href="https://github.com/kjhoerr" rel="me" aria-label="My GitHub account with my most active personal projects">
+ <i role="img" class="icon fa-github"></i>
+ kjhoerr on GitHub
+ </a>
+</section>
+<section>
+ <a href="https://github.com/kjhoerr/pantry" aria-label="Source code repository of Kevin&apos;s current pet project Pantry">
+ <i role="img" class="icon fa-code"></i>
+ Pantry (pet project)
+ </a>
+</section>
+<section>
+ <a href="https://cybr.es/@kjhoerr" rel="me" aria-label="My Mastodon account">
+ <i role="img" class="icon fa-mastodon"></i>
+ @kjhoerr@cybr.es
+ </a>
+</section> \ No newline at end of file
diff --git a/src/pages/index.tsx b/src/pages/index.tsx
deleted file mode 100644
index fe407c4..0000000
--- a/src/pages/index.tsx
+++ /dev/null
@@ -1,73 +0,0 @@
-import React from "react";
-import { StaticImage } from "gatsby-plugin-image";
-import { FaCode, FaGithub, FaMastodon } from "react-icons/fa";
-import { BlockLink, Layout } from "../components";
-import { BlockBody, BlockHeader } from "../styles";
-
-const IndexPage = (): React.ReactElement => {
- return (
- <Layout>
- <div>
- <StaticImage
- src="../images/main.png"
- alt="Picture of Kevin Hoerr"
- placeholder="blurred"
- layout="fixed"
- width={350}
- height={350}
- />
- </div>
- <BlockHeader>Hello!</BlockHeader>
- <BlockBody>
- <p>
- I&apos;m a computer science and math graduate from Millersville
- University. I work as a Solutions Architect and specialize in
- development operations and systems validation for web applications.
- </p>
- <p>
- During my time at Millersville I was the lead Linux admin for the
- Cyber Defense Organization (CDO). In addition to constructing a new
- computer lab for our efforts, we participated in NCL and MACCDC.
- </p>
- <p>
- Most of my development experience is focused around full stack
- development. For the front-end I use TypeScript and ReactJS using
- create-react-app or NextJS. For back-end systems I have used both Java
- with Spring Boot and rust with actix-web extensively. To mediate APIs
- I have used Apache Kafka, OpenAPI, and GraphQL.
- </p>
- <p>
- My free time is spent engaging in general computing hobbies. When
- I&apos;m not trying out new application frameworks, I am fiddling
- around with Guix or NixOS. I run a kubernetes cluster at home to
- manage, maintain, and secure my personal network as well as
- experimenting with distributed workloads.
- </p>
- <em>- Kevin H.</em>
- </BlockBody>
- <BlockLink
- href="https://github.com/kjhoerr"
- rel="me"
- aria-label="My GitHub account with my most active personal projects"
- >
- <FaGithub /> kjhoerr on GitHub
- </BlockLink>
- <BlockLink
- href="https://github.com/kjhoerr/pantry"
- aria-label="Source code repository of Kevin's current pet project Pantry"
- >
- <FaCode /> Pantry (pet project)
- </BlockLink>
- <BlockLink
- href="https://cybr.es/@kjhoerr"
- rel="me"
- aria-label="My Mastodon account"
- >
- <FaMastodon /> @kjhoerr@cybr.es
- </BlockLink>
- </Layout>
- );
-};
-
-export default IndexPage;
-export { Head } from "../components/SEO";
diff --git a/src/static/favicon-32x32.png b/src/static/favicon-32x32.png
new file mode 100644
index 0000000..baa2b5e
--- /dev/null
+++ b/src/static/favicon-32x32.png
Binary files differ
diff --git a/src/static/icons/code.svg b/src/static/icons/code.svg
new file mode 100644
index 0000000..ddd0a7d
--- /dev/null
+++ b/src/static/icons/code.svg
@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" fill="#000000" aria-hidden="true" focusable="false" height="20" width="20" viewBox="0 0 640 512">
+ <!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2023 Fonticons, Inc.-->
+ <path d="M392.8 1.2c-17-4.9-34.7 5-39.6 22l-128 448c-4.9 17 5 34.7 22 39.6s34.7-5 39.6-22l128-448c4.9-17-5-34.7-22-39.6zm80.6 120.1c-12.5 12.5-12.5 32.8 0 45.3L562.7 256l-89.4 89.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l112-112c12.5-12.5 12.5-32.8 0-45.3l-112-112c-12.5-12.5-32.8-12.5-45.3 0zm-306.7 0c-12.5-12.5-32.8-12.5-45.3 0l-112 112c-12.5 12.5-12.5 32.8 0 45.3l112 112c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L77.3 256l89.4-89.4c12.5-12.5 12.5-32.8 0-45.3z"/>
+</svg> \ No newline at end of file
diff --git a/src/static/icons/github.svg b/src/static/icons/github.svg
new file mode 100644
index 0000000..2179508
--- /dev/null
+++ b/src/static/icons/github.svg
@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" fill="#000000" aria-hidden="true" focusable="false" height="20" width="20" viewBox="0 0 496 512">
+ <!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2023 Fonticons, Inc.-->
+ <path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3 .3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5 .3-6.2 2.3zm44.2-1.7c-2.9 .7-4.9 2.6-4.6 4.9 .3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3 .7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3 .3 2.9 2.3 3.9 1.6 1 3.6 .7 4.3-.7 .7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3 .7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3 .7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/>
+</svg> \ No newline at end of file
diff --git a/src/static/icons/icon-144x144.png b/src/static/icons/icon-144x144.png
new file mode 100644
index 0000000..18f5e4f
--- /dev/null
+++ b/src/static/icons/icon-144x144.png
Binary files differ
diff --git a/src/static/icons/icon-192x192.png b/src/static/icons/icon-192x192.png
new file mode 100644
index 0000000..7d6c60c
--- /dev/null
+++ b/src/static/icons/icon-192x192.png
Binary files differ
diff --git a/src/static/icons/icon-256x256.png b/src/static/icons/icon-256x256.png
new file mode 100644
index 0000000..9f331e2
--- /dev/null
+++ b/src/static/icons/icon-256x256.png
Binary files differ
diff --git a/src/static/icons/icon-384x384.png b/src/static/icons/icon-384x384.png
new file mode 100644
index 0000000..39bdf43
--- /dev/null
+++ b/src/static/icons/icon-384x384.png
Binary files differ
diff --git a/src/static/icons/icon-48x48.png b/src/static/icons/icon-48x48.png
new file mode 100644
index 0000000..951cbe7
--- /dev/null
+++ b/src/static/icons/icon-48x48.png
Binary files differ
diff --git a/src/static/icons/icon-512x512.png b/src/static/icons/icon-512x512.png
new file mode 100644
index 0000000..be1b067
--- /dev/null
+++ b/src/static/icons/icon-512x512.png
Binary files differ
diff --git a/src/static/icons/icon-72x72.png b/src/static/icons/icon-72x72.png
new file mode 100644
index 0000000..ac5beec
--- /dev/null
+++ b/src/static/icons/icon-72x72.png
Binary files differ
diff --git a/src/static/icons/icon-96x96.png b/src/static/icons/icon-96x96.png
new file mode 100644
index 0000000..5ae5b70
--- /dev/null
+++ b/src/static/icons/icon-96x96.png
Binary files differ
diff --git a/src/static/icons/mastodon.svg b/src/static/icons/mastodon.svg
new file mode 100644
index 0000000..b298458
--- /dev/null
+++ b/src/static/icons/mastodon.svg
@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" fill="#000000" aria-hidden="true" focusable="false" height="20" width="20" viewBox="0 0 448 512">
+ <!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2023 Fonticons, Inc.-->
+ <path d="M433 179.1c0-97.2-63.7-125.7-63.7-125.7-62.5-28.7-228.6-28.4-290.5 0 0 0-63.7 28.5-63.7 125.7 0 115.7-6.6 259.4 105.6 289.1 40.5 10.7 75.3 13 103.3 11.4 50.8-2.8 79.3-18.1 79.3-18.1l-1.7-36.9s-36.3 11.4-77.1 10.1c-40.4-1.4-83-4.4-89.6-54a102.5 102.5 0 0 1 -.9-13.9c85.6 20.9 158.7 9.1 178.8 6.7 56.1-6.7 105-41.3 111.2-72.9 9.8-49.8 9-121.5 9-121.5zm-75.1 125.2h-46.6v-114.2c0-49.7-64-51.6-64 6.9v62.5h-46.3V197c0-58.5-64-56.6-64-6.9v114.2H90.2c0-122.1-5.2-147.9 18.4-175 25.9-28.9 79.8-30.8 103.8 6.1l11.6 19.5 11.6-19.5c24.1-37.1 78.1-34.8 103.8-6.1 23.7 27.3 18.4 53 18.4 175z"/>
+</svg> \ No newline at end of file
diff --git a/src/static/manifest.webmanifest b/src/static/manifest.webmanifest
new file mode 100644
index 0000000..516cdf7
--- /dev/null
+++ b/src/static/manifest.webmanifest
@@ -0,0 +1,34 @@
+{
+ "name": "Kevin J Hoerr",
+ "short_name": "kjhoerr",
+ "start_url": "/",
+ "background_color": "#e1e1e1",
+ "theme_color": "#e1e1e1",
+ "display": "browser",
+ "icons": [
+ { "src": "icons/icon-48x48.png", "sizes": "48x48", "type": "image/png" },
+ { "src": "icons/icon-72x72.png", "sizes": "72x72", "type": "image/png" },
+ { "src": "icons/icon-96x96.png", "sizes": "96x96", "type": "image/png" },
+ {
+ "src": "icons/icon-144x144.png",
+ "sizes": "144x144",
+ "type": "image/png"
+ },
+ {
+ "src": "icons/icon-192x192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "icons/icon-256x256.png",
+ "sizes": "256x256",
+ "type": "image/png"
+ },
+ {
+ "src": "icons/icon-384x384.png",
+ "sizes": "384x384",
+ "type": "image/png"
+ },
+ { "src": "icons/icon-512x512.png", "sizes": "512x512", "type": "image/png" }
+ ]
+}
diff --git a/src/static/static/81e0da73927123f3f6b0c9a2d0750e76/6cac9/main.webp b/src/static/static/81e0da73927123f3f6b0c9a2d0750e76/6cac9/main.webp
new file mode 100644
index 0000000..185b64e
--- /dev/null
+++ b/src/static/static/81e0da73927123f3f6b0c9a2d0750e76/6cac9/main.webp
Binary files differ
diff --git a/src/static/static/81e0da73927123f3f6b0c9a2d0750e76/88e48/main.png b/src/static/static/81e0da73927123f3f6b0c9a2d0750e76/88e48/main.png
new file mode 100644
index 0000000..5139f93
--- /dev/null
+++ b/src/static/static/81e0da73927123f3f6b0c9a2d0750e76/88e48/main.png
Binary files differ
diff --git a/src/static/styles.css b/src/static/styles.css
new file mode 100644
index 0000000..90e7842
--- /dev/null
+++ b/src/static/styles.css
@@ -0,0 +1,205 @@
+body {
+ background-color: #e1e1e1;
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAGXpUWHRUaXRsZQAACNdLSkzOTi/KL81LAQAWSwQhPQTyzQAAABt6VFh0QXV0aG9yAAAI1/NOLcvMU/DITy0qAgAYDwQeUS3vvwAAAZNJREFUeNrt3bFtQ0EMREH5x+q/M3Wi3IJaMGR7yHtbwCWDBY4J+fV4PL5vH879fr9tz/P5/JV3rzAcjI+DhAGBhAGBhAGBhAGBhAGBhAGBhAGBhAGBhAGBhAGBhAGBhAGBhAGBhAGBhAGBhAGBhAGBhAGBhAGBhDHglxXG/+RdjisMB2N1QyZirAWZirESZDLGOpDpGKtANmCsAdmCsQJkE8Z4kG0Yo0E2YowF2YoxEmQzxjiQ7RijQE7AGANyCsYIkJMweJDTMGiQEzFYkFMxSJCTMTiQ0zEokDAgkDAgkDAgkDAgkDAgkDAgkDAgkDAgkDAgkDAgkDAgkDAgkDAgkDAgkDAgkDAgkDAgkDAgkDAgkDAgkDAgkDAgkDAgkDAgkDAgkDAgkDAgkDAgkDAgkDAgkDAgkDAgkDAgkDAgkDAGTuph/E3e5bjCcDBGNOS03fRXGA4GDXLq1YYrDAeDBDn9nskVhoNBgYQBgYQBgYQBgYQBgYQBgYQBgYQBgYQBgYQBgYQBgYQBgYQBgYTxs7wA+yQwVSKvoHMAAAAASUVORK5CYII=);
+ background-repeat: repeat;
+ font-display: serif;
+ font-family: Merriweather, serif;
+ font-size: 16px;
+ color: #000;
+}
+
+::selection {
+ background-color: #999;
+ color: #fff;
+}
+
+em,
+p,
+q {
+ display: block;
+ text-indent: 28px;
+}
+
+p {
+ margin: 0 0 16px;
+}
+
+p > a,
+p > a:hover,
+p > a:visited {
+ color: #000;
+ padding: 1px 3px;
+ text-decoration: none;
+}
+
+p > a,
+p > a:visited {
+ background-color: #e1e1e1;
+}
+
+p > a:hover {
+ background-color: #d5d5d5;
+}
+
+i.icon {
+ display: inline-block;
+ stroke-width: 0;
+ overflow-clip-margin: content-box;
+ overflow: hidden;
+ margin-bottom: -4px;
+ height: 20px;
+ width: 20px;
+ filter: invert(37%) sepia(0%) saturate(1906%) hue-rotate(177deg)
+ brightness(97%) contrast(72%);
+}
+i.icon.fa-code {
+ background-image: url(icons/code.svg);
+}
+i.icon.fa-github {
+ background-image: url(icons/github.svg);
+}
+i.icon.fa-mastodon {
+ background-image: url(icons/mastodon.svg);
+}
+
+article {
+ width: 350px;
+ margin: 0px auto;
+ margin-bottom: 120px;
+ padding-top: 136px;
+}
+
+article > picture {
+ width: 350px;
+ height: 350px;
+}
+
+section {
+ background-color: #fff;
+ border: 1px #000 solid;
+ border-left: 3px #000 solid;
+ border-right: 3px #000 solid;
+ padding: 4px 8px;
+}
+
+section:has(h1) {
+ border: 0px;
+ background-color: #000;
+ width: 100%;
+ margin-top: 3px;
+ padding: 4px 0px 0px;
+}
+
+section + section {
+ margin-top: 3px;
+}
+
+section:has(h1) + section {
+ margin-top: 0px;
+}
+
+section > h1 {
+ text-align: center;
+ color: #fff;
+ font-size: 36px;
+ font-weight: bold;
+ margin: 0px;
+ padding: 0px;
+}
+
+section:has(a) {
+ padding: 0;
+}
+
+section:has(a):hover {
+ background-color: #ddd;
+ color: #222;
+}
+
+section > a {
+ padding: 8px;
+ width: 328px;
+ display: block;
+ text-align: center;
+ -webkit-text-decoration: none;
+ text-decoration: none;
+ color: #777;
+}
+
+section > a:visited,
+section > a:active {
+ padding: 8px;
+ width: 328px;
+ display: block;
+ text-align: center;
+ -webkit-text-decoration: none;
+ text-decoration: none;
+ color: #777;
+}
+
+section:last-child,
+section:last-child > a {
+ border-bottom-left-radius: 18px;
+ border-bottom-right-radius: 18px;
+}
+
+footer {
+ width: 100%;
+ position: fixed;
+ left: 0px;
+ bottom: 0px;
+ text-align: center;
+ font-size: 12px;
+}
+
+footer > span {
+ padding: 2px;
+ background: #e1e1e1;
+}
+
+@media (prefers-color-scheme: dark) {
+ body {
+ background-color: #424242;
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAAAXNSR0IArs4c6QAAAltJREFUeF7t3cuKwzAMheHprs/VZd//YbqbIS10CLk5sSTr8mfvYPOBQPIhuT2fz98f4ef1egm/0d/r7ve7yqZu0iBg9DmJgoDRhzGtFgMBox9DDAQMGQwREDDkMLpBwJDF6AIBQx7jMggYOhiXQMDQwzgNAoYuxikQMPQxmkHAsMFoAgHDDuMQBAxbjF0QMOwxNkHAGIOxCgLGOIwFCBhjMWYgYIzH+IKA4QPjDfJ4PMRDDn6O99mJViBB45zpQSJhTJUqNUg0jNQlKyJGWpCoGClBImOkA4mOkQokA0YakCwYKUAyYYQHyYYRGiQjRliQrBghQTJjhAPJjhEKpAJGGJAqGCFAKmG4B6mG4RqkIoZbkKoYLkEqY7gDqY7hCgSMT6jIReoEjP+E13AQMOZxu6EgYCyzj8NAwFgPog4BAWM7FWwOAsZ+RNsUBIzjvLwZCBjHGGZ9CBhtGCYgYLRjqIOAcQ5DFQSM8xhqIGBcw1ABAeM6hjgIGH0YoiBg9GOIgYAhgyECAoYcRjcIGLIYXSBgyGNcBgFDB+MSCBh6GKdBwNDFOAUChj5GMwgYNhhNIGDYYRyCgGGLsQsChj3GJggYYzBWQcAYh7EAAWMsxgwEjPEYXxAwfGC8QaR/Tqx5tApf4A4DUgFjqlQhQKpghChZlTDcg1TDcA1SEcMtSFUMlyCVMdyBVMdwBQLGp6V20YeA8T/fGA4CxnzYNBQEjOXkbxgIGOtj2CEgYGzPxM1BwNi/oDAFAeP4tsgMBIxjDLM+BIw2DBMQMNox1EHAOIehCgLGeYxpxR8MpN5wf4mWVQAAAABJRU5ErkJggg==);
+ color: #ddd;
+ }
+
+ p > a,
+ p > a:hover,
+ p > a:visited {
+ color: #fff;
+ }
+
+ i.icon {
+ filter: invert(77%) sepia(0%) saturate(0%) hue-rotate(26deg) brightness(88%)
+ contrast(92%);
+ }
+
+ section {
+ background-color: #000;
+ border-color: #777;
+ }
+
+ section:has(h1) {
+ background-color: #777;
+ }
+
+ section > h1 {
+ color: #000;
+ }
+
+ section > a,
+ section > a:visited,
+ section > a:active {
+ color: #aaa;
+ }
+
+ section:has(a):hover {
+ background-color: #222;
+ color: #ddd;
+ }
+
+ footer > span {
+ background: #646464;
+ }
+}
diff --git a/src/styles/BlockAnchor.ts b/src/styles/BlockAnchor.ts
deleted file mode 100644
index 05eb2a2..0000000
--- a/src/styles/BlockAnchor.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import styled from "styled-components";
-
-export default styled.a`
- padding: 8px;
- width: 328px;
- display: block;
- text-align: center;
- -webkit-text-decoration: none;
- text-decoration: none;
- color: #666;
- &:visited,
- &:active {
- padding: 8px;
- width: 328px;
- display: block;
- text-align: center;
- -webkit-text-decoration: none;
- text-decoration: none;
- color: #666;
- }
-`;
diff --git a/src/styles/BlockBody.ts b/src/styles/BlockBody.ts
deleted file mode 100644
index 8fb655e..0000000
--- a/src/styles/BlockBody.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import styled from "styled-components";
-import BlockAnchor from "./BlockAnchor";
-
-export default styled.div`
- & + & {
- margin-top: 3px;
- }
-
- background-color: #fff;
- border: 1px #000 solid;
- border-left: 3px #000 solid;
- border-right: 3px #000 solid;
-
- padding: ${(props) => (props.theme.link ? "0" : "4px 8px")};
-
- & > ${BlockAnchor} {
- &:hover {
- background-color: #ddd;
- color: #222;
- }
- }
- &:last-child,
- &:last-child > ${BlockAnchor} {
- border-bottom-left-radius: 18px;
- border-bottom-right-radius: 18px;
- }
-`;
diff --git a/src/styles/BlockHeader.ts b/src/styles/BlockHeader.ts
deleted file mode 100644
index eb6fe93..0000000
--- a/src/styles/BlockHeader.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import styled from "styled-components";
-
-export default styled.div`
- background-color: #000;
- width: 100%;
- text-align: center;
- color: #fff;
- font-size: 36px;
- font-weight: bold;
- margin-top: 3px;
- padding-top: 4px;
-`;
diff --git a/src/styles/Content.ts b/src/styles/Content.ts
delet