Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions src/components/BackLink.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
interface Props {
href: string;
text: string;
}

const { href, text } = Astro.props;
---

<a class="back-link" {href}>{text}</a>

<style>
.back-link::before {
content: "←";
display: inline-block;
margin-right: 4px;
}

.back-link::before:hover {
text-decoration: none;
}

.back-link {
display: inline-block;
color: var(--color-primary);
text-decoration: none;
margin-bottom: var(--spacing-md);
font-weight: 500;
}

.back-link:hover {
text-decoration: underline;
}
</style>
35 changes: 35 additions & 0 deletions src/components/Tag.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
import { useI18n } from "../i18n/utils";

interface Props {
name: string;
}

const { name } = Astro.props;

const { translatePath } = useI18n(Astro.url);
---

<a class="tag" href={translatePath(`/blog/tags/${encodeURIComponent(name)}`)}>
{name}
</a>

<style>
a.tag {
text-decoration: none;
background: var(--color-gray-light);
color: var(--color-gray);
padding: 0.25rem 0.75rem;
border-radius: 12px;
font-size: 0.875rem;
font-weight: 500;
}

a.tag:visited {
text-decoration: none;
}

a.tag:hover {
background-color: #cecece;
}
</style>
5 changes: 5 additions & 0 deletions src/i18n/ch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ const ts = {
"nav.contact": "Kontakt",
"nav.blog": "Blog",
"nav.language": "Sprach",
"nav.backToBlog": "Zrügg zum Blog",
"nav.backToServices": "Zrügg zu Services",
"nav.backToJobs": "Zrügg zu Jobs",
"nav.backToCustomers": "Zrügg zu Chunde",

// Buttons & CTAs
"cta.freeWorkshop": "Gratis Cloud Readiness Workshop",
Expand Down Expand Up @@ -83,6 +87,7 @@ const ts = {
"blog.title": "Blog",
"blog.subtitle": "Tipps, Aleitige u Best Practices für modärni Cloud-Büetz",
"blog.empty": "No keni Blog-Artikel verfüegbar. Lueg gly mau wieder ine!",
"blog.allPosts": "Alle Artikel",

// Customers Page
"customers.page.title": "Üsi Chunde",
Expand Down
5 changes: 5 additions & 0 deletions src/i18n/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ const de = {
"nav.contact": "Kontakt",
"nav.blog": "Blog",
"nav.language": "Sprache",
"nav.backToBlog": "Zurück zum Blog",
"nav.backToServices": "Zurück zu Services",
"nav.backToJobs": "Zurück zu Jobs",
"nav.backToCustomers": "Zurück zu Kunden",

// Buttons & CTAs
"cta.freeWorkshop": "Kostenloser Cloud Readiness Workshop",
Expand Down Expand Up @@ -85,6 +89,7 @@ const de = {
"blog.subtitle":
"Tipps, Anleitungen und Best Practices für moderne Cloud-Entwicklung",
"blog.empty": "Noch keine Blog-Artikel verfügbar. Schau bald wieder vorbei!",
"blog.allPosts": "Alle Artikel",

// Customers Page
"customers.page.title": "Unsere Kunden",
Expand Down
5 changes: 5 additions & 0 deletions src/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ const en = {
"nav.contact": "Contact",
"nav.blog": "Blog",
"nav.language": "Language",
"nav.backToBlog": "Back to Blog",
"nav.backToServices": "Back to Services",
"nav.backToJobs": "Back to Jobs",
"nav.backToCustomers": "Back to Customers",

// Buttons & CTAs
"cta.freeWorkshop": "Free Cloud Readiness Workshop",
Expand Down Expand Up @@ -83,6 +87,7 @@ const en = {
"blog.title": "Blog",
"blog.subtitle": "Tips, guides, and best practices to work with cloud tech",
"blog.empty": "No blog posts yet. Check back soon!",
"blog.allPosts": "All Posts",

// Customers Page
"customers.page.title": "Our Customers",
Expand Down
21 changes: 19 additions & 2 deletions src/layouts/CollectionPage.astro
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import Layout from "./Layout.astro";
import SEO from "../components/SEO.astro";
import Title from "../components/Title.astro";
import BackLink from "../components/BackLink.astro";

interface Props {
pageTitle: string;
Expand All @@ -11,17 +12,33 @@ interface Props {
lang: string;
isEmpty?: boolean;
emptyMessage?: string;
backLink?: { href: string; text: string };
}

const { pageTitle, title, subtitle, description, lang, isEmpty, emptyMessage } =
Astro.props;
const {
pageTitle,
title,
subtitle,
description,
lang,
isEmpty,
emptyMessage,
backLink,
} = Astro.props;
---

<Layout>
<SEO slot="head" title={pageTitle} {description} {lang} />
<Title title={title} subtitle={subtitle} />
<main class="collection-page">
<div class="container">
{
backLink && (
<div style="margin-bottom: 1em">
<BackLink href={backLink.href} text={backLink.text} />
</div>
)
}
<div class="collection-grid">
<slot />
</div>
Expand Down
15 changes: 2 additions & 13 deletions src/layouts/ContentDetailPage.astro
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import Layout from "./Layout.astro";
import SEO from "../components/SEO.astro";
import StructuredData from "../components/StructuredData.astro";
import BackLink from "../components/BackLink.astro";

interface MetaItem {
label: string;
Expand Down Expand Up @@ -44,7 +45,7 @@ const {
<main class="content-detail">
<article class="container">
<header class="content-header">
<a href={backLink.href} class="back-link">{backLink.text}</a>
<BackLink href={backLink.href} text={backLink.text} />
<slot name="header-before" />
<h1>{title}</h1>
{
Expand Down Expand Up @@ -92,18 +93,6 @@ const {
margin-bottom: 3rem;
}

.back-link {
display: inline-block;
color: var(--color-primary);
text-decoration: none;
margin-bottom: var(--spacing-md);
font-weight: 500;
}

.back-link:hover {
text-decoration: underline;
}

h1 {
font-size: 2.5rem;
line-height: 1.2;
Expand Down
4 changes: 2 additions & 2 deletions src/pages/[lang]/about/jobs/[...slug].astro
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export async function getStaticPaths() {
const { job } = Astro.props;
const { Content } = await render(job);

const { lang, translatePath } = useI18n(Astro.url);
const { lang, translatePath, t } = useI18n(Astro.url);

const title = `${job.data.title} | Jobs`;
const description = `Join bespinian as a ${job.data.title}. ${job.data.location ? "Location: " + job.data.location + "." : ""} ${job.data.employment ? job.data.employment + " position." : ""} We're looking for talented individuals to help companies succeed with cloud-native technologies.`;
Expand All @@ -29,7 +29,7 @@ if (job.data.employment) metaItems.push({ label: job.data.employment });
{lang}
backLink={{
href: translatePath("/about/jobs"),
text: "← Back to Jobs",
text: t("nav.backToJobs"),
}}
meta={metaItems}
structuredData={{
Expand Down
50 changes: 41 additions & 9 deletions src/pages/[lang]/blog/[...slug].astro
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import ContentDetailPage from "../../../layouts/ContentDetailPage.astro";
import { getCollectionStaticPaths } from "../../../lib/paths";
import { useI18n } from "../../../i18n/utils";
import { formatDate } from "../../../lib/formatters";
import Tag from "../../../components/Tag.astro";
import rss from "../../../assets/rss.svg";

export async function getStaticPaths() {
return getCollectionStaticPaths("blog");
Expand All @@ -13,7 +15,7 @@ export async function getStaticPaths() {
const { post } = Astro.props;
const { Content } = await render(post);

const { lang, translatePath } = useI18n(Astro.url);
const { lang, translatePath, t } = useI18n(Astro.url);

const formattedDate = formatDate(post.data.pubDate, lang);

Expand All @@ -28,7 +30,7 @@ const canonicalUrl = new URL(Astro.url.pathname, Astro.site).toString();
title={post.data.title}
{description}
{lang}
backLink={{ href: translatePath("/blog"), text: "← Back to Blog" }}
backLink={{ href: translatePath("/blog"), text: t("nav.backToBlog") }}
meta={[
{ label: post.data.author },
{ label: formattedDate, datetime: post.data.pubDate.toISOString() },
Expand Down Expand Up @@ -61,10 +63,17 @@ const canonicalUrl = new URL(Astro.url.pathname, Astro.site).toString();
}

<div slot="header-after" class="tags">
{post.data.tags.map((tag: string) => <span class="tag">{tag}</span>)}
{post.data.tags.map((tag: string) => <Tag name={tag} />)}
</div>

<Content />
<div class="actions">
<a href={translatePath("/blog")} class="btn">{t("blog.allPosts")}</a>
<a href="/rss.xml" class="btn rss">
<img width="10" src={rss.src} alt="RSS Feed" />
RSS
</a>
</div>
</ContentDetailPage>

<style>
Expand All @@ -87,12 +96,35 @@ const canonicalUrl = new URL(Astro.url.pathname, Astro.site).toString();
gap: 0.5rem;
}

.tag {
background: #f0f0f0;
color: var(--color-gray);
padding: 0.25rem 0.75rem;
border-radius: 12px;
.actions {
margin: 5em 0;
padding-top: 2em;
border-top: 1px solid #cecece;
display: flex;
gap: 1rem;
}

.btn {
display: inline-flex;
text-decoration: none !important;
color: var(--color-primary);
padding: 6px 16px;
border: 1px solid var(--color-background-primary);
background-color: var(--color-background-secondary);
border-radius: 6px;
font-size: 0.875rem;
font-weight: 500;
}

.btn:hover {
background-color: var(--color-background-primary);
color: var(--color-secondary);
}

.btn:hover > img {
filter: invert(1);
}

.btn img {
margin: 0 0.25rem;
}
</style>
50 changes: 50 additions & 0 deletions src/pages/[lang]/blog/tags/[tag].astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
Comment thread
chickenbreeder marked this conversation as resolved.
import type { GetStaticPaths } from "astro";
import { getCollection } from "astro:content";
import CollectionPage from "../../../../layouts/CollectionPage.astro";
import BlogCard from "../../../../components/BlogCard.astro";
import { useI18n } from "../../../../i18n/utils";
import { languages } from "../../../../i18n/ui";
import { sortByDateDesc } from "../../../../lib/formatters";

export const getStaticPaths = (async () => {
const allPosts = await getCollection("blog");

const uniqueTags = [
...new Set(allPosts.flatMap((post) => post.data.tags || [])),
];

return uniqueTags.flatMap((tag) =>
Object.keys(languages).map((lang) => {
const filteredPosts = allPosts.filter((post) =>
post.data.tags?.includes(tag),
);
const sortedPosts = sortByDateDesc(filteredPosts);

return {
params: { lang, tag },
props: { posts: sortedPosts },
};
}),
);
}) satisfies GetStaticPaths;

const { lang, translatePath, t } = useI18n(Astro.url);
const { tag } = Astro.params;
const { posts } = Astro.props;

const title = `Blog | ${tag}`;
const description = `Tagged "${tag}"`;
---

<CollectionPage
pageTitle={title}
title={t("blog.title")}
subtitle={description}
{description}
{lang}
isEmpty={posts.length === 0}
backLink={{ href: translatePath("/blog"), text: t("nav.backToBlog") }}
>
{posts.map(({ id, data }) => <BlogCard {id} {...data} />)}
</CollectionPage>
Loading