aboutsummaryrefslogtreecommitdiff
path: root/src/components
diff options
context:
space:
mode:
Diffstat (limited to 'src/components')
-rw-r--r--src/components/Analytics.astro18
-rw-r--r--src/components/Comments.astro1
-rw-r--r--src/components/Head.astro33
-rw-r--r--src/components/Header.astro16
-rw-r--r--src/components/Icons/Email.astro20
-rw-r--r--src/components/Icons/GitHub.astro22
-rw-r--r--src/components/Icons/LinkedIn.astro21
-rw-r--r--src/components/Icons/RSS.astro17
-rw-r--r--src/components/JsonLd.astro13
-rw-r--r--src/components/Pagination.astro35
-rw-r--r--src/components/PostElement.astro40
-rw-r--r--src/components/PostSummary.astro49
-rw-r--r--src/components/Sections/LatestPosts.astro43
-rw-r--r--src/components/Sections/SocialLinks.astro19
-rw-r--r--src/components/Sections/Welcome.astro7
15 files changed, 249 insertions, 105 deletions
diff --git a/src/components/Analytics.astro b/src/components/Analytics.astro
index 428ad4f..0c22f52 100644
--- a/src/components/Analytics.astro
+++ b/src/components/Analytics.astro
@@ -1,17 +1 @@
----
-type Props = {
- readonly title: string;
-};
-
-const path = Astro.url.pathname;
-const { title } = Astro.props;
----
-
-<!-- AppMetrix -->
-<script is:inline src="https://appmetrix.com/pixel/T5X0z12SoASBV8Dv"></script>
-
-<!-- GoatCounter -->
-<script is:inline data-goatcounter="https://analytics.popov.link/count" src="//gc.zgo.at/count.js"></script>
-<noscript>
- <img alt="pixel" src={`https://analytics.popov.link/count?p=${encodeURI(path)}&t=${encodeURI(title)}`} />
-</noscript>
+<script is:inline defer src="https://appmetrix.com/pixel/T5X0z12SoASBV8Dv"></script>
diff --git a/src/components/Comments.astro b/src/components/Comments.astro
index 5474d89..c2d6531 100644
--- a/src/components/Comments.astro
+++ b/src/components/Comments.astro
@@ -15,6 +15,7 @@ const theme = "transparent_dark";
<script
is:inline
+ defer
src="https://giscus.app/client.js"
data-category-id={categoryId}
data-category={category}
diff --git a/src/components/Head.astro b/src/components/Head.astro
index 8ed2224..3fded95 100644
--- a/src/components/Head.astro
+++ b/src/components/Head.astro
@@ -1,14 +1,22 @@
---
+import type { WithContext, Thing } from "schema-dts";
+import JsonLd from "./JsonLd.astro";
+
type Props = {
readonly description: string;
+ readonly preview: string;
+ readonly schema: WithContext<Thing>;
readonly title: string;
};
-const canonicalURL = new URL(Astro.url.pathname, Astro.site);
-const { description, title } = Astro.props;
+const { description, preview, schema, title } = Astro.props;
+
+const canonicalUrl = new URL(Astro.url.pathname, Astro.site);
+const previewUrl = new URL(preview, Astro.site);
---
<head>
+ <!-- Meta Tags -->
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
@@ -18,12 +26,29 @@ const { description, title } = Astro.props;
<link href="/feed.xml" rel="alternate" title="RSS" type="application/atom+xml" />
<link href="/sitemap-index.xml" rel="sitemap" />
- <link href={canonicalURL} rel="canonical" />
+ <link href={canonicalUrl} rel="canonical" />
<title>{title}</title>
- <link rel="icon" href="/favicon.png" />
+ <!-- Icons -->
+ <link rel="icon" type="image/x-icon" href="/favicon.ico" />
+ <link rel="icon" type="image/png" href="/favicon.png" />
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
<link rel="manifest" href="/manifest.json" />
<meta name="theme-color" content="#ffffff" />
+
+ <!-- Open Graph -->
+ <meta property="og:type" content="website" />
+ <meta property="og:title" content={title} />
+ <meta property="og:description" content={description} />
+ <meta property="og:image" content={previewUrl} />
+ <meta property="og:url" content={canonicalUrl} />
+
+ <!-- Twitter Cards -->
+ <meta name="twitter:card" content="summary_large_image" />
+ <meta name="twitter:title" content={title} />
+ <meta name="twitter:description" content={description} />
+ <meta name="twitter:image" content={previewUrl} />
+
+ <JsonLd schema={schema} />
</head>
diff --git a/src/components/Header.astro b/src/components/Header.astro
new file mode 100644
index 0000000..f9a0c57
--- /dev/null
+++ b/src/components/Header.astro
@@ -0,0 +1,16 @@
+<style lang="scss">
+ a {
+ margin-right: 1.5rem;
+
+ &:last-child {
+ margin-right: 0;
+ }
+ }
+</style>
+
+<header>
+ <nav aria-label="Navigation">
+ <a href="/" lang="en" aria-label="Home">Home</a>
+ <a href="/blog/" lang="en" aria-label="Blog">Blog</a>
+ </nav>
+</header>
diff --git a/src/components/Icons/Email.astro b/src/components/Icons/Email.astro
new file mode 100644
index 0000000..42391e9
--- /dev/null
+++ b/src/components/Icons/Email.astro
@@ -0,0 +1,20 @@
+<style lang="scss">
+ @use "../../scss/variables" as *;
+
+ a {
+ color: $colorText;
+ display: inline-block;
+ margin: 0 0.5rem;
+ }
+
+ svg {
+ vertical-align: middle;
+ }
+</style>
+
+<a href="mailto:valentin@popov.link" title="E-Mail" rel="noopener" target="_blank">
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-label="E-Mail" aria-hidden="true">
+ <path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path>
+ <polyline points="22,6 12,13 2,6"></polyline>
+ </svg>
+</a>
diff --git a/src/components/Icons/GitHub.astro b/src/components/Icons/GitHub.astro
new file mode 100644
index 0000000..845dafc
--- /dev/null
+++ b/src/components/Icons/GitHub.astro
@@ -0,0 +1,22 @@
+<style lang="scss">
+ @use "../../scss/variables" as *;
+
+ a {
+ color: $colorText;
+ display: inline-block;
+ margin: 0 0.5rem;
+ }
+
+ svg {
+ vertical-align: middle;
+ }
+</style>
+
+<a href="https://github.com/valentineus" title="GitHub" rel="noopener" target="_blank">
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-label="GitHub" aria-hidden="true">
+ <path
+ d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"
+ >
+ </path>
+ </svg>
+</a>
diff --git a/src/components/Icons/LinkedIn.astro b/src/components/Icons/LinkedIn.astro
new file mode 100644
index 0000000..bbcf6b4
--- /dev/null
+++ b/src/components/Icons/LinkedIn.astro
@@ -0,0 +1,21 @@
+<style lang="scss">
+ @use "../../scss/variables" as *;
+
+ a {
+ color: $colorText;
+ display: inline-block;
+ margin: 0 0.5rem;
+ }
+
+ svg {
+ vertical-align: middle;
+ }
+</style>
+
+<a href="https://www.linkedin.com/in/valentineus/" title="LinkedIn" rel="noopener" target="_blank">
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-label="LinkedIn" aria-hidden="true">
+ <path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z"></path>
+ <rect x="2" y="9" width="4" height="12"></rect>
+ <circle cx="4" cy="4" r="2"></circle>
+ </svg>
+</a>
diff --git a/src/components/Icons/RSS.astro b/src/components/Icons/RSS.astro
new file mode 100644
index 0000000..f487fb8
--- /dev/null
+++ b/src/components/Icons/RSS.astro
@@ -0,0 +1,17 @@
+<style lang="scss">
+ a {
+ display: inline-block;
+ }
+
+ svg {
+ vertical-align: middle;
+ }
+</style>
+
+<a href="/feed.xml" title="RSS Feed" rel="noopener" target="_blank">
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-label="RSS Feed" aria-hidden="true">
+ <path d="M4 11a9 9 0 0 1 9 9"></path>
+ <path d="M4 4a16 16 0 0 1 16 16"></path>
+ <circle cx="5" cy="19" r="1"></circle>
+ </svg>
+</a>
diff --git a/src/components/JsonLd.astro b/src/components/JsonLd.astro
new file mode 100644
index 0000000..b58efd7
--- /dev/null
+++ b/src/components/JsonLd.astro
@@ -0,0 +1,13 @@
+---
+import type { WithContext, Thing } from "schema-dts";
+
+type Props = {
+ readonly schema: WithContext<Thing>;
+};
+
+const { schema } = Astro.props;
+const json = JSON.stringify(schema);
+---
+
+<!-- JSON-LD -->
+<script is:inline type="application/ld+json" set:html={json} />
diff --git a/src/components/Pagination.astro b/src/components/Pagination.astro
deleted file mode 100644
index 0d656df..0000000
--- a/src/components/Pagination.astro
+++ /dev/null
@@ -1,35 +0,0 @@
----
-type Props = {
- readonly nextUrl?: string;
- readonly prevUrl?: string;
-};
-
-const { nextUrl, prevUrl } = Astro.props;
----
-
-<style lang="scss">
- div {
- text-align: center;
- }
-
- span {
- margin: 0 2em;
- }
-</style>
-
-<div>
- {
- prevUrl && (
- <span>
- <a href={prevUrl}>&lt; Prev</a>
- </span>
- )
- }
- {
- nextUrl && (
- <span>
- <a href={nextUrl}>Next &gt;</a>
- </span>
- )
- }
-</div>
diff --git a/src/components/PostElement.astro b/src/components/PostElement.astro
new file mode 100644
index 0000000..8b4b7c4
--- /dev/null
+++ b/src/components/PostElement.astro
@@ -0,0 +1,40 @@
+---
+import { type CollectionEntry } from "astro:content";
+import dayjs from "dayjs";
+
+type Props = {
+ readonly post: CollectionEntry<"blog">;
+};
+
+const { post } = Astro.props;
+const { remarkPluginFrontmatter } = await post.render();
+
+const formattedDate = dayjs(post.data.datePublished.toString()).format("MMMM DD, YYYY");
+const datePublished = post.data.datePublished.toISOString();
+---
+
+<style lang="scss">
+ @use "../scss/variables" as *;
+
+ a {
+ color: $colorText;
+ }
+
+ small {
+ font-size: $fontSizeBase * 0.75;
+ opacity: 0.5;
+ }
+</style>
+
+<li>
+ <article>
+ <a href={`/blog/${post.slug}`} lang={post.data.lang}>{post.data.title}</a>
+ <div>
+ <small>
+ <time datetime={datePublished} lang="en">{formattedDate}</time>
+ <span>•</span>
+ <span>{remarkPluginFrontmatter.minutesRead}</span>
+ </small>
+ </div>
+ </article>
+</li>
diff --git a/src/components/PostSummary.astro b/src/components/PostSummary.astro
deleted file mode 100644
index 329f1ce..0000000
--- a/src/components/PostSummary.astro
+++ /dev/null
@@ -1,49 +0,0 @@
----
-import { type CollectionEntry } from "astro:content";
-import dayjs from "dayjs";
-
-type Props = {
- readonly post: CollectionEntry<"blog">;
-};
-
-const { post } = Astro.props;
-const { remarkPluginFrontmatter } = await post.render();
-const formattedDate = dayjs(post.data.pubDate.toString()).format("MMMM DD, YYYY");
----
-
-<style lang="scss">
- @import "../scss/_variables.scss";
-
- a {
- color: $colorText;
- display: block;
- padding-bottom: 3rem;
-
- &:visited {
- color: $colorText;
- }
- }
-
- h2 {
- color: $colorBlossom;
- font-size: 1.25em;
- margin: 0.5em 0;
- }
-
- div {
- font-size: $fontSizeBase * 0.75;
- opacity: 0.5;
- }
-</style>
-
-<a href={`/blog/${post.slug}`}>
- <article>
- <div>
- <time datetime={post.data.pubDate.toISOString()}>{formattedDate}</time>
- <span>•</span>
- <span>{remarkPluginFrontmatter.minutesRead}</span>
- </div>
- <h2>{post.data.title}</h2>
- <p>{post.data.description}</p>
- </article>
-</a>
diff --git a/src/components/Sections/LatestPosts.astro b/src/components/Sections/LatestPosts.astro
new file mode 100644
index 0000000..e514ff5
--- /dev/null
+++ b/src/components/Sections/LatestPosts.astro
@@ -0,0 +1,43 @@
+---
+import { getCollection } from "astro:content";
+import dayjs from "dayjs";
+import RSSIcon from "../Icons/RSS.astro";
+
+const posts = await getCollection("blog", ({ data }) => {
+ return data.draft !== true;
+});
+
+posts.sort((a, b) => b.data.datePublished.getTime() - a.data.datePublished.getTime());
+
+const latestPosts = posts.slice(0, 5);
+---
+
+<style lang="scss">
+ @use "../../scss/variables" as *;
+
+ small {
+ font-size: $fontSizeBase * 0.75;
+ opacity: 0.5;
+ }
+</style>
+
+<section>
+ <h2>Latest posts <RSSIcon /></h2>
+ <ul>
+ {
+ latestPosts.map((post) => (
+ <li>
+ <a href={`/blog/${post.slug}`} lang={post.data.lang}>
+ {post.data.title}
+ </a>
+
+ <small>
+ <time datetime={post.data.datePublished.toISOString()} lang="en">
+ {dayjs(post.data.datePublished.toString()).format("MMMM DD, YYYY")}
+ </time>
+ </small>
+ </li>
+ ))
+ }
+ </ul>
+</section>
diff --git a/src/components/Sections/SocialLinks.astro b/src/components/Sections/SocialLinks.astro
new file mode 100644
index 0000000..c804b60
--- /dev/null
+++ b/src/components/Sections/SocialLinks.astro
@@ -0,0 +1,19 @@
+---
+import GitHubIcon from "../Icons/GitHub.astro";
+import LinkedInIcon from "../Icons/LinkedIn.astro";
+import EmailIcon from "../Icons/Email.astro";
+---
+
+<style lang="scss">
+ div {
+ margin-bottom: 2rem;
+ }
+</style>
+
+<section>
+ <div>
+ <GitHubIcon />
+ <LinkedInIcon />
+ <EmailIcon />
+ </div>
+</section>
diff --git a/src/components/Sections/Welcome.astro b/src/components/Sections/Welcome.astro
new file mode 100644
index 0000000..ee7cae5
--- /dev/null
+++ b/src/components/Sections/Welcome.astro
@@ -0,0 +1,7 @@
+<section>
+ <div>
+ <h1>Hi, I'm Valentin 👋</h1>
+ <p>I'm a professional software developer currently working as a project manager and team lead. On my personal website, I share thoughts on tech, leadership, and digital life.</p>
+ <p>Welcome, and feel free to explore!</p>
+ </div>
+</section>