diff --git a/.pugrc b/.pugrc
index 611be22..5a39ffc 100644
--- a/.pugrc
+++ b/.pugrc
@@ -45,6 +45,7 @@
"email": ["hello", "at", "dailysh.it"],
"name": "Michael W. Czechowski",
"logoSvg": "./src/assets/nls.svg",
+ "logoSvgInverted": "./src/assets/nls_inverted.svg",
"emojiSvg": "./src/assets/waving-hand.svg",
"jobTitle": ["Enterprise Software Architect", "Digital Transformation Expert"]
},
@@ -129,7 +130,7 @@
],
"sectionTitles": {
"computerScience": "Computer Science",
- "expertise": "Software Architecture and Development"
+ "expertise": "Software Architecture and Development"
},
"courseInstitutions": {
"dhbw": "Duale Hochschule Baden-Württemberg (DHBW)",
@@ -1164,7 +1165,7 @@
"ariaLabel": "The twelve-factor methodology can be applied to apps written in any programming language, and which use any combination of backing services (database, queue, memory cache, etc).",
"text": "The 12-Factor App"
},
- "text": " Microservices and Software-as-a-Service Methodology"
+ "text": "Microservices and Software-as-a-Service Methodology"
},
{
"text": "Testing Pyramid"
diff --git a/index.pug b/index.pug
index b3be88e..038fca9 100644
--- a/index.pug
+++ b/index.pug
@@ -32,12 +32,15 @@ html.scroll-smooth(lang=lang)
});
sections.forEach((section) => sectionObserver(section.id).observe(section));
- let yearsOfAge = 0;
- let yearsOfDeveloping = 0;
+ // tailwindcss set correct dark/light theme depending on client preference
+ // https://tailwindcss.com/docs/dark-mode#toggling-dark-mode
- setInterval(() => {
- yearsOfAge = (new Date().getTime() - new Date("1988-10-07").getTime()) / 1000 / 60 / 60 / 24 / 365.25;
- yearsOfDeveloping = (new Date().getTime() - new Date("2005-07-07").getTime()) / 1000 / 60 / 60 / 24 / 365.25;
- document.getElementById("yearsOfAge").innerText = yearsOfAge.toFixed(6);
- document.getElementById("yearsOfDeveloping").innerText = yearsOfDeveloping.toFixed(6);
- }, 500);
+ // let yearsOfAge = 0;
+ // let yearsOfDeveloping = 0;
+ //
+ // setInterval(() => {
+ // yearsOfAge = (new Date().getTime() - new Date("1988-10-07").getTime()) / 1000 / 60 / 60 / 24 / 365.25;
+ // yearsOfDeveloping = (new Date().getTime() - new Date("2005-07-07").getTime()) / 1000 / 60 / 60 / 24 / 365.25;
+ // document.getElementById("yearsOfAge").innerText = yearsOfAge.toFixed(6);
+ // document.getElementById("yearsOfDeveloping").innerText = yearsOfDeveloping.toFixed(6);
+ // }, 500);
diff --git a/src/assets/CV_2024_Michael-Werner-Czechowski_de.pdf b/src/assets/CV_2024_Michael-Werner-Czechowski_de.pdf
new file mode 100644
index 0000000..4a9a594
Binary files /dev/null and b/src/assets/CV_2024_Michael-Werner-Czechowski_de.pdf differ
diff --git a/src/assets/nls.svg b/src/assets/nls.svg
index f5bc8b3..59068dd 100644
--- a/src/assets/nls.svg
+++ b/src/assets/nls.svg
@@ -1,1225 +1,36 @@
-
-
-
-
+
+
+
+
diff --git a/src/assets/nls_inverted.svg b/src/assets/nls_inverted.svg
new file mode 100644
index 0000000..6f4b332
--- /dev/null
+++ b/src/assets/nls_inverted.svg
@@ -0,0 +1,36 @@
+
+
+
+
diff --git a/src/components/Academia.pug b/src/components/Academia.pug
index 18933fa..27a38ed 100644
--- a/src/components/Academia.pug
+++ b/src/components/Academia.pug
@@ -2,15 +2,15 @@ include Collapsable
include Title
include Container
-section#academia.bg-nls-black.text-white
- .p-8(class="sm:p-20 min-h-[120vh]")
+section#academia
+ .p-8.bg-white.text-nls-black(class="dark:bg-nls-black dark:text-white sm:p-20 min-h-[120vh]")
+Container
// region Skills
- +Title("h2")= academia.sectionTitles.expertise
+ +Title("h2") !{academia.sectionTitles.expertise}
.mb-8.max-w-prose
each paragraph, i in academia.expertise.intro
- - const additionalClasses = i !== 0 ? "indent-3" : "mb-2 font-serif leading-widest sm:text-md text-sm tracking-tight w-5/6 text-white";
- p.text-slate-200(class=`hover:text-white transition ${additionalClasses}`) !{paragraph}
+ - const additionalClasses = i !== 0 ? "indent-3" : "mb-2 font-serif leading-widest sm:text-md text-sm tracking-tight w-5/6";
+ p(class=`text-slate-700 dark:text-slate-300 ${additionalClasses}`) !{paragraph}
// endregion
// region Expertise
@@ -31,15 +31,15 @@ section#academia.bg-nls-black.text-white
.mb-8.max-w-prose.prose(class="lg:prose-xl")
each paragraph, i in academia.intro
- const additionalClasses = i !== 0 ? "indent-3" : "mb-2 font-serif leading-widest sm:text-md text-sm tracking-tight w-5/6 text-white";
- p.text-slate-200(class=`hover:text-white transition ${additionalClasses}`) !{paragraph}
+ p.text-slate-700(class=`dark:text-slate-300 ${additionalClasses}`) !{paragraph}
// endregion
// region Courses
.grid.grid-cols-1.gap-6.mb-8(class="md:grid-cols-1")
div
details.mb-4
- summary.rounded-sm.text-white.transition.underline-offset-2.mb-2.cursor-pointer(
- class="focus:outline-none focus:z-10 focus:ring-4 focus:ring-white focus:bg-white focus:text-black focus:no-underline",
+ summary.rounded-sm.text-nls-black.transition.underline-offset-2.mb-2.cursor-pointer(
+ class="dark:text-white focus:outline-none focus:z-10 focus:ring-4 focus:ring-nls-black dark:focus:ring-white focus:bg-nls-black focus:text-white dark:focus:bg-white dark:focus:text-nls-black focus:no-underline",
onclick="umami.track('collapsable clicked', { category: 'courses dhbw', visitDuration: getVisitDuration() })"
)= academia.courseInstitutions.dhbw
ul.list-disc.list-inside
@@ -47,8 +47,8 @@ section#academia.bg-nls-black.text-white
li= course
div
details.mb-4
- summary.rounded-sm.text-white.transition.underline-offset-2.mb-2.cursor-pointer(
- class="focus:outline-none focus:z-10 focus:ring-4 focus:ring-white focus:bg-white focus:text-black focus:no-underline",
+ summary.rounded-sm.text-md.text-nls-black.transition.underline-offset-2.mb-2.cursor-pointer(
+ class="sm:text-lg dark:text-white focus:outline-none focus:z-10 focus:ring-4 focus:ring-nls-black dark:focus:ring-white focus:bg-nls-black focus:text-white dark:focus:bg-white dark:focus:text-nls-black focus:no-underline",
onclick="umami.track('collapsable clicked', { category: 'courses leibniz-fh', visitDuration: getVisitDuration() })"
)= academia.courseInstitutions.lfh
ul.list-disc.list-inside
diff --git a/src/components/Collapsable.pug b/src/components/Collapsable.pug
index 3018203..a342b6c 100644
--- a/src/components/Collapsable.pug
+++ b/src/components/Collapsable.pug
@@ -6,11 +6,11 @@ mixin Collapsable(data, open)
div
details.mb-4(open=isExpanded)
- summary.rounded-sm.transition.mb-2.cursor-pointer.text-md.font-semibold.mb-2.cursor-pointer(
- class=`sm:text-lg text-nls-${color} focus:outline-none focus:z-10 focus:ring-4 focus:ring-nls-${color} focus:bg-nls-${color} focus:text-black focus:no-underline`,
+ summary(
+ class=`rounded-sm transition mb-2 cursor-pointer text-md font-semibold mb-2 cursor-pointer sm:text-lg text-nls-${color} dark:text-nls-${color} focus:outline-none focus:z-10 focus:ring-4 focus:ring-nls-${color} focus:bg-nls-${color} focus:text-black focus:no-underline`,
onclick=`umami.track('collapsable clicked', { category: '${category}', visitDuration: getVisitDuration() })`
)= data.summary
- ul.list-disc.list-inside.text-stone-300
+ ul.list-disc.list-inside.text-slate-600(class="dark:text-stone-300")
if data.items
each item in data.items
li
@@ -18,15 +18,15 @@ mixin Collapsable(data, open)
= item.text
if item.links
each link, index in item.links
- a.transition.underline-offset-2.underline(
- class=`text-nls-${color} hover:text-white hover:decoration-2`,
+ a(
+ class=`transition underline-offset-2 underline text-nls-${color} hover:text-nls-black dark:hover:text-white hover:decoration-2`,
href=link.url,
title=link.description,
target="_blank",
aria-label=link.description,
rel="noopener noreferrer",
onclick=`umami.track('${linkEventName}', { category: '${category}', position: 'collapsable', label: '${link.label}', visitDuration: getVisitDuration() })`
- )= link.text
+ ) #{link.text}
if index < item.links.length - 1
| ,
if item.suffix
diff --git a/src/components/Footer.pug b/src/components/Footer.pug
index 6552364..6684173 100644
--- a/src/components/Footer.pug
+++ b/src/components/Footer.pug
@@ -5,15 +5,15 @@ mixin Link(href, label, target, rel)
- const eventCategory = "footer";
- const onclick = `umami.track('${eventName}', { category: 'icons', position: 'footer', label: '${label}', visitDuration: getVisitDuration() })`;
- a.transition-colors.text-white(href=href, class="hover:text-amber-300", target=target, rel=rel, onclick=onclick)
+ a.transition-colors.text-nls-black(href=href, class="dark:text-white hover:text-amber-300", target=target, rel=rel, onclick=onclick)
block
mixin Svg
svg.w-24.h-24(class="sm:w-8 sm:h-8", aria-hidden="true", fill="currentColor", viewbox="0 0 24 24")
block
-footer#footer.bg-nls-black.text-white
- .p-8(class="sm:p-20 min-h-[120vh]")
+footer#footer
+ .p-8.bg-white.text-nls-black(class="dark:bg-nls-black dark:text-white sm:p-20 min-h-[120vh]")
+Container
// region Contact
h2.text-5xl.mb-4 #{footer.title}
@@ -44,14 +44,14 @@ footer#footer.bg-nls-black.text-white
style="fill: currentColor"
)
- a.transition-colors.text-white.uppercase.font-semibold(
+ a.transition-colors.text-nls-black.uppercase.font-semibold(
href=footer.emailLink,
- class="hover:text-amber-300",
+ class="dark:text-white hover:text-amber-300",
rel="noopener noreferrer",
onclick="umami.track('email clicked', { position: 'footer', visitDuration: getVisitDuration() })"
) #{footer.emailText}
- +Link("./src/assets/CV_2019_Michael-Werner-Czechowski_en.pdf", "CV", "_blank", "noopener noreferrer")
+ +Link("./src/assets/CV_2024_Michael-Werner-Czechowski_de.pdf", "CV", "_blank", "noopener noreferrer")
| CV
+Link("https://git.dailysh.it/nextlevelshit/dailysh.it", "gitea", "_blank", "noopener noreferrer")= footer.gitea
diff --git a/src/components/Head.pug b/src/components/Head.pug
index d6157f6..dc0904c 100644
--- a/src/components/Head.pug
+++ b/src/components/Head.pug
@@ -51,6 +51,7 @@ head
script(src="https://cdn.tailwindcss.com")
script.
tailwind.config = {
+ darkMode: "media",
theme: {
fontFamily: {
mono: ["Roboto Mono", "monospace"],
@@ -146,3 +147,26 @@ head
const getVisitDuration = () => {
return Math.floor((Date.now() - window.visitDuration) / 1000);
};
+
+ // Check for saved user preference, if any, on load of the website
+ const darkMode = localStorage.getItem("darkMode");
+
+ // If no preference is set, check system preference
+ if (darkMode === null) {
+ if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
+ document.documentElement.classList.add("dark");
+ localStorage.setItem("darkMode", "dark");
+ }
+ } else if (darkMode === "dark") {
+ document.documentElement.classList.add("dark");
+ }
+
+ function toggleDarkMode() {
+ if (document.documentElement.classList.contains("dark")) {
+ document.documentElement.classList.remove("dark");
+ localStorage.setItem("darkMode", "light");
+ } else {
+ document.documentElement.classList.add("dark");
+ localStorage.setItem("darkMode", "dark");
+ }
+ }
diff --git a/src/components/Landingpage.pug b/src/components/Landingpage.pug
index e0c4fb4..1ccc045 100644
--- a/src/components/Landingpage.pug
+++ b/src/components/Landingpage.pug
@@ -1,13 +1,16 @@
-header.bg-nls-black.text-white
+header.bg-white.text-nls-black(class="dark:text-white dark:bg-nls-black")
+ //button.absolute.top-0.right-0.w-8.h-8.m-3.p-3.rounded-full.bg-slate-300(
+ // onclick="toggleDarkMode()"
+ //)
+ // div(class="block dark:hidden")
+ // span.sr-only Toggle dark mode
+ // | 🌙
+ // div(class="hidden dark:block")
+ // span.sr-only Toggle light mode
+ // | ☀️
+
.teaser.p-8.flex.flex-col.items-center.justify-center(class="sm:p-20")
.max-w-3xl.mb-8.relative(class="w-4/5 min-h-[90vh]")
- img.absolute.z-10.left-0.right-0.mx-auto.opacity-0.transition(
- class="top-[30vh] max-h-[37vh] peer-hover:opacity-100 peer-hover:scale-150",
- src=landingpage.emojiSvg
- )
-
- img.absolute.z-0.left-0.right-0.mx-auto.transition(class="h-[54vh] peer-hover:opacity-60 peer-hover:scale-50", src=landingpage.logoSvg)
-
.peer.absolute.bottom-0.left-0.right-0.z-40.text-center.max-w-3xl.center.py-8
h2.tracking-widest.text-xl.font-semibold.opacity-80.transition(class="sm:text-2xl peer-hover:opacity-100", itemprop="name")= landingpage.name
@@ -17,24 +20,12 @@ header.bg-nls-black.text-white
wbr
|
| & #{landingpage.jobTitle[1]}
- a.group.text-2xl.mt-8(
- class="sm:text-5xl sm:mt-16",
- onclick="umami.track('email clicked', { position: 'title', visitDuration: getVisitDuration() })",
- onmouseover="umami.track('email hovered', { position: 'title', visitDuration: getVisitDuration() })",
- href=footer.emailLink,
- rel="noopener noreferrer",
- itemprop="email"
- )
- .whitespace-nowrap.items-center.transition(class="group-hover:opacity-100")
- span(class="group-hover:opacity-100") #{landingpage.email[0]}
- span.opacity-20 –
- span.opacity-90(class="group-hover:opacity-20") #{landingpage.email[1]}
- span.opacity-20 –
- span.opacity-90(class="group-hover:opacity-20") #{landingpage.email[2]}
- .hidden
- | Years of age:
- span#yearsOfAge
- |
- | |
- | Years of developing:
- span#yearsOfDeveloping
+
+ //img.absolute.z-10.left-0.right-0.mx-auto.opacity-0.transition(
+ // class="top-[30vh] max-h-[37vh] peer-hover:opacity-100 peer-hover:scale-150",
+ // src=landingpage.emojiSvg
+ //)
+
+ img.absolute.z-0.left-0.right-0.mx-auto.transition.invisible(class="dark:visible h-[54vh]", src=landingpage.logoSvg)
+
+ img.absolute.z-0.left-0.right-0.mx-auto.transition.visible(class="dark:invisible h-[54vh]", src=landingpage.logoSvgInverted)
diff --git a/src/components/Professional.pug b/src/components/Professional.pug
index 4042518..b6dca8b 100644
--- a/src/components/Professional.pug
+++ b/src/components/Professional.pug
@@ -1,18 +1,14 @@
-include Collapsable
-include Title
-include Container
-
-section#professional.bg-nls-black.text-white
+section#professional.bg-white.text-nls-black(class="dark:bg-nls-black dark:text-white")
.p-8(class="sm:p-20 min-h-[120vh]")
+Container
+Title("h2")= professional.title
- p.mb-4.max-w-prose.prose.indent-3(class="lg:prose-xl")
+ p.mb-4.max-w-prose.prose.indent-3(class="lg:prose-xl dark:prose-invert")
| #{professional.description}
- p.mb-8.max-w-prose.prose(class="lg:prose-xl")
+ p.mb-8.max-w-prose.prose(class="lg:prose-xl dark:prose-invert")
| #{professional.principlesIntro}
.list-disc.list-inside.mb-8
each person, i in professional.principlesPeople
- - const data = {summary: `${person.name} — ${person.concept}`, color: "white", category: "professional"};
+ - const data = {summary: `${person.name} — ${person.concept}`, color: "text-nls-black dark:text-white", category: "professional"};
- const isOpen = i === 0;
+Collapsable(data, isOpen)
each paragraph, j in person.paragraphs