From d0fc2c0567b8049f0d6d15c2c021b81bd7972d98 Mon Sep 17 00:00:00 2001
From: Don-Damiano <133017758+Don-Damiano@users.noreply.github.com>
Date: Thu, 29 Jan 2026 12:09:44 +0100
Subject: [PATCH 1/2] feat(i18n): add route map and seo links
---
src/components/Header.astro | 13 ++-
src/components/LanguageSwitch.astro | 13 ++-
src/i18n/routes.ts | 103 ++++++++++++++++++
src/layouts/BaseLayout.astro | 33 +++++-
src/pages/en/case-studies.astro | 3 +-
src/pages/en/case-studies/[slug].astro | 7 +-
src/pages/en/contact.astro | 3 +-
src/pages/en/faq/index.astro | 4 +-
src/pages/en/for-founders.astro | 3 +-
src/pages/en/how-we-work.astro | 3 +-
src/pages/en/index.astro | 3 +-
src/pages/en/services/deployment/index.astro | 4 +-
src/pages/en/services/design/index.astro | 4 +-
src/pages/en/services/development/index.astro | 4 +-
src/pages/en/services/index.astro | 3 +-
.../en/services/infrastructure/index.astro | 4 +-
src/pages/en/services/post-launch/index.astro | 4 +-
src/pages/pl/case-studies.astro | 3 +-
src/pages/pl/case-studies/[slug].astro | 9 +-
src/pages/pl/faq/index.astro | 4 +-
src/pages/pl/for-founders.astro | 3 +-
src/pages/pl/how-we-work.astro | 3 +-
src/pages/pl/index.astro | 3 +-
src/pages/pl/kontakt.astro | 3 +-
src/pages/pl/oferta/index.astro | 3 +-
.../pl/oferta/infrastruktura/index.astro | 4 +-
src/pages/pl/oferta/obsluga/index.astro | 4 +-
src/pages/pl/oferta/programowanie/index.astro | 4 +-
src/pages/pl/oferta/projektowanie/index.astro | 4 +-
src/pages/pl/oferta/wdrozenie/index.astro | 4 +-
30 files changed, 214 insertions(+), 48 deletions(-)
create mode 100644 src/i18n/routes.ts
diff --git a/src/components/Header.astro b/src/components/Header.astro
index 5a656ed..34e527b 100644
--- a/src/components/Header.astro
+++ b/src/components/Header.astro
@@ -1,7 +1,14 @@
---
import LanguageSwitch from "./LanguageSwitch.astro";
+import type { RouteKey, RouteParams } from "../i18n/routes";
-const { lang } = Astro.props;
+type Props = {
+ lang: "pl" | "en";
+ routeKey: RouteKey;
+ routeParams?: RouteParams;
+};
+
+const { lang, routeKey, routeParams } = Astro.props as Props;
const homeHref = lang === "pl" ? "/pl/" : "/en/";
@@ -94,7 +101,7 @@ const nav = lang === "pl"
{nav.map((i) => (
{i.label}
))}
-
+
@@ -111,4 +118,4 @@ const nav = lang === "pl"
navLinks.dataset.open = nextState;
});
}
-
\ No newline at end of file
+
diff --git a/src/components/LanguageSwitch.astro b/src/components/LanguageSwitch.astro
index 58bda4e..f4f67b4 100644
--- a/src/components/LanguageSwitch.astro
+++ b/src/components/LanguageSwitch.astro
@@ -1,9 +1,16 @@
---
-const { lang } = Astro.props;
+import { getRoutePaths } from "../i18n/routes";
+import type { RouteKey, RouteParams } from "../i18n/routes";
+type Props = {
+ lang: "pl" | "en";
+ routeKey: RouteKey;
+ routeParams?: RouteParams;
+};
+
+const { lang, routeKey, routeParams } = Astro.props as Props;
const isPL = lang === "pl";
-const plHref = "/pl/";
-const enHref = "/en/";
+const { pl: plHref, en: enHref } = getRoutePaths(routeKey, routeParams);
---
PL
diff --git a/src/i18n/routes.ts b/src/i18n/routes.ts
new file mode 100644
index 0000000..ec4403b
--- /dev/null
+++ b/src/i18n/routes.ts
@@ -0,0 +1,103 @@
+export type RouteKey =
+ | "home"
+ | "services"
+ | "servicesDevelopment"
+ | "servicesDesign"
+ | "servicesInfrastructure"
+ | "servicesDeployment"
+ | "servicesPostLaunch"
+ | "contact"
+ | "caseStudies"
+ | "caseStudy"
+ | "howWeWork"
+ | "faq"
+ | "forFounders";
+
+export type RouteParams = {
+ slug?: string;
+};
+
+type RouteBuilder = (params?: RouteParams) => string;
+
+type RouteEntry = {
+ pl: string | RouteBuilder;
+ en: string | RouteBuilder;
+};
+
+const buildCaseStudyPath = (basePath: string): RouteBuilder => (params) => {
+ if (!params?.slug) {
+ throw new Error("Missing slug for case study route.");
+ }
+
+ return `${basePath}${params.slug}/`;
+};
+
+const routes: Record
= {
+ home: {
+ pl: "/pl/",
+ en: "/en/",
+ },
+ services: {
+ pl: "/pl/oferta/",
+ en: "/en/services/",
+ },
+ servicesDevelopment: {
+ pl: "/pl/oferta/programowanie/",
+ en: "/en/services/development/",
+ },
+ servicesDesign: {
+ pl: "/pl/oferta/projektowanie/",
+ en: "/en/services/design/",
+ },
+ servicesInfrastructure: {
+ pl: "/pl/oferta/infrastruktura/",
+ en: "/en/services/infrastructure/",
+ },
+ servicesDeployment: {
+ pl: "/pl/oferta/wdrozenie/",
+ en: "/en/services/deployment/",
+ },
+ servicesPostLaunch: {
+ pl: "/pl/oferta/obsluga/",
+ en: "/en/services/post-launch/",
+ },
+ contact: {
+ pl: "/pl/kontakt/",
+ en: "/en/contact/",
+ },
+ caseStudies: {
+ pl: "/pl/case-studies/",
+ en: "/en/case-studies/",
+ },
+ caseStudy: {
+ pl: buildCaseStudyPath("/pl/case-studies/"),
+ en: buildCaseStudyPath("/en/case-studies/"),
+ },
+ howWeWork: {
+ pl: "/pl/how-we-work/",
+ en: "/en/how-we-work/",
+ },
+ faq: {
+ pl: "/pl/faq/",
+ en: "/en/faq/",
+ },
+ forFounders: {
+ pl: "/pl/for-founders/",
+ en: "/en/for-founders/",
+ },
+};
+
+const resolvePath = (value: string | RouteBuilder, params?: RouteParams): string =>
+ typeof value === "function" ? value(params) : value;
+
+export const getRoutePaths = (
+ routeKey: RouteKey,
+ params?: RouteParams,
+): { pl: string; en: string } => {
+ const entry = routes[routeKey];
+
+ return {
+ pl: resolvePath(entry.pl, params),
+ en: resolvePath(entry.en, params),
+ };
+};
diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro
index a9baeca..1b8ac68 100644
--- a/src/layouts/BaseLayout.astro
+++ b/src/layouts/BaseLayout.astro
@@ -1,10 +1,32 @@
---
-const { title, description = "", lang = "en" } = Astro.props;
-
import "../styles/global.css";
import Header from "../components/Header.astro";
import Footer from "../components/Footer.astro";
import ContactLauncher from "../components/ContactLauncher.astro";
+import { getRoutePaths } from "../i18n/routes";
+import type { RouteKey, RouteParams } from "../i18n/routes";
+
+type Props = {
+ title?: string;
+ description?: string;
+ lang?: "pl" | "en";
+ routeKey: RouteKey;
+ routeParams?: RouteParams;
+};
+
+const {
+ title,
+ description = "",
+ lang = "en",
+ routeKey,
+ routeParams,
+} = Astro.props as Props;
+
+const baseUrl = "https://rocketdeploy.dev";
+const { pl: plPath, en: enPath } = getRoutePaths(routeKey, routeParams);
+const plUrl = new URL(plPath, baseUrl).toString();
+const enUrl = new URL(enPath, baseUrl).toString();
+const canonicalUrl = lang === "pl" ? plUrl : enUrl;
---
@@ -19,12 +41,17 @@ import ContactLauncher from "../components/ContactLauncher.astro";
{description && }
{description && }
{description && }
+
+
+
+
+
diff --git a/src/pages/en/case-studies.astro b/src/pages/en/case-studies.astro
index 84fb817..61c6ddb 100644
--- a/src/pages/en/case-studies.astro
+++ b/src/pages/en/case-studies.astro
@@ -7,6 +7,7 @@ const entries = await getCollection("en-case-studies");
@@ -26,4 +27,4 @@ const entries = await getCollection("en-case-studies");
))}
-
\ No newline at end of file
+
diff --git a/src/pages/en/case-studies/[slug].astro b/src/pages/en/case-studies/[slug].astro
index ad38f68..7b27130 100644
--- a/src/pages/en/case-studies/[slug].astro
+++ b/src/pages/en/case-studies/[slug].astro
@@ -14,7 +14,12 @@ const { entry } = Astro.props;
const { Content } = await entry.render();
---
-
+
diff --git a/src/pages/en/contact.astro b/src/pages/en/contact.astro
index c2457d7..127abc9 100644
--- a/src/pages/en/contact.astro
+++ b/src/pages/en/contact.astro
@@ -4,6 +4,7 @@ import BaseLayout from "../../layouts/BaseLayout.astro";
@@ -139,4 +140,4 @@ import BaseLayout from "../../layouts/BaseLayout.astro";
showTick();
};
-
\ No newline at end of file
+
diff --git a/src/pages/en/faq/index.astro b/src/pages/en/faq/index.astro
index 8d3811f..64b9dc2 100644
--- a/src/pages/en/faq/index.astro
+++ b/src/pages/en/faq/index.astro
@@ -2,7 +2,7 @@
import BaseLayout from "../../../layouts/BaseLayout.astro";
---
-
+
FAQ
@@ -129,4 +129,4 @@ import BaseLayout from "../../../layouts/BaseLayout.astro";
-
\ No newline at end of file
+
diff --git a/src/pages/en/for-founders.astro b/src/pages/en/for-founders.astro
index 0f95272..96a559e 100644
--- a/src/pages/en/for-founders.astro
+++ b/src/pages/en/for-founders.astro
@@ -4,6 +4,7 @@ import BaseLayout from "../../layouts/BaseLayout.astro";
@@ -125,4 +126,4 @@ import BaseLayout from "../../layouts/BaseLayout.astro";
-
\ No newline at end of file
+
diff --git a/src/pages/en/how-we-work.astro b/src/pages/en/how-we-work.astro
index 2552b3e..b6003f6 100644
--- a/src/pages/en/how-we-work.astro
+++ b/src/pages/en/how-we-work.astro
@@ -4,6 +4,7 @@ import BaseLayout from "../../layouts/BaseLayout.astro";
@@ -97,4 +98,4 @@ import BaseLayout from "../../layouts/BaseLayout.astro";
-
\ No newline at end of file
+
diff --git a/src/pages/en/index.astro b/src/pages/en/index.astro
index 2f5e89e..78660ab 100644
--- a/src/pages/en/index.astro
+++ b/src/pages/en/index.astro
@@ -6,6 +6,7 @@ import HeroVisual from "../../components/HeroVisual.astro";
@@ -211,4 +212,4 @@ import HeroVisual from "../../components/HeroVisual.astro";
-
\ No newline at end of file
+
diff --git a/src/pages/en/services/deployment/index.astro b/src/pages/en/services/deployment/index.astro
index 18de8a3..156b892 100644
--- a/src/pages/en/services/deployment/index.astro
+++ b/src/pages/en/services/deployment/index.astro
@@ -2,7 +2,7 @@
import BaseLayout from "../../../../layouts/BaseLayout.astro";
---
-
+
Deployment
@@ -41,4 +41,4 @@ import BaseLayout from "../../../../layouts/BaseLayout.astro";
-
\ No newline at end of file
+
diff --git a/src/pages/en/services/design/index.astro b/src/pages/en/services/design/index.astro
index 74759b0..3cbbe1a 100644
--- a/src/pages/en/services/design/index.astro
+++ b/src/pages/en/services/design/index.astro
@@ -2,7 +2,7 @@
import BaseLayout from "../../../../layouts/BaseLayout.astro";
---
-
+
Design
@@ -45,4 +45,4 @@ import BaseLayout from "../../../../layouts/BaseLayout.astro";
-
\ No newline at end of file
+
diff --git a/src/pages/en/services/development/index.astro b/src/pages/en/services/development/index.astro
index 9a5c502..1f91d2a 100644
--- a/src/pages/en/services/development/index.astro
+++ b/src/pages/en/services/development/index.astro
@@ -2,7 +2,7 @@
import BaseLayout from "../../../../layouts/BaseLayout.astro";
---
-
+
Development
@@ -45,4 +45,4 @@ import BaseLayout from "../../../../layouts/BaseLayout.astro";
-
\ No newline at end of file
+
diff --git a/src/pages/en/services/index.astro b/src/pages/en/services/index.astro
index 2ce3d3b..ae77c6a 100644
--- a/src/pages/en/services/index.astro
+++ b/src/pages/en/services/index.astro
@@ -4,6 +4,7 @@ import BaseLayout from "../../../layouts/BaseLayout.astro";
@@ -107,4 +108,4 @@ import BaseLayout from "../../../layouts/BaseLayout.astro";
-
\ No newline at end of file
+
diff --git a/src/pages/en/services/infrastructure/index.astro b/src/pages/en/services/infrastructure/index.astro
index f55f58b..bd267dc 100644
--- a/src/pages/en/services/infrastructure/index.astro
+++ b/src/pages/en/services/infrastructure/index.astro
@@ -2,7 +2,7 @@
import BaseLayout from "../../../../layouts/BaseLayout.astro";
---
-
+
Infrastructure
@@ -44,4 +44,4 @@ import BaseLayout from "../../../../layouts/BaseLayout.astro";
-
\ No newline at end of file
+
diff --git a/src/pages/en/services/post-launch/index.astro b/src/pages/en/services/post-launch/index.astro
index 4c0ec7c..3508980 100644
--- a/src/pages/en/services/post-launch/index.astro
+++ b/src/pages/en/services/post-launch/index.astro
@@ -2,7 +2,7 @@
import BaseLayout from "../../../../layouts/BaseLayout.astro";
---
-
+
Post-launch support
@@ -60,4 +60,4 @@ import BaseLayout from "../../../../layouts/BaseLayout.astro";
-
\ No newline at end of file
+
diff --git a/src/pages/pl/case-studies.astro b/src/pages/pl/case-studies.astro
index fd8d39d..6a02e9a 100644
--- a/src/pages/pl/case-studies.astro
+++ b/src/pages/pl/case-studies.astro
@@ -7,6 +7,7 @@ const entries = await getCollection("pl-case-studies");
@@ -26,4 +27,4 @@ const entries = await getCollection("pl-case-studies");
))}
-
\ No newline at end of file
+
diff --git a/src/pages/pl/case-studies/[slug].astro b/src/pages/pl/case-studies/[slug].astro
index 0293c6a..0cba16a 100644
--- a/src/pages/pl/case-studies/[slug].astro
+++ b/src/pages/pl/case-studies/[slug].astro
@@ -14,7 +14,12 @@ const { entry } = Astro.props;
const { Content } = await entry.render();
---
-
+
@@ -29,4 +34,4 @@ const { Content } = await entry.render();
-
\ No newline at end of file
+
diff --git a/src/pages/pl/faq/index.astro b/src/pages/pl/faq/index.astro
index 6257d08..b8d2010 100644
--- a/src/pages/pl/faq/index.astro
+++ b/src/pages/pl/faq/index.astro
@@ -2,7 +2,7 @@
import BaseLayout from "../../../layouts/BaseLayout.astro";
---
-
+
FAQ
@@ -128,4 +128,4 @@ import BaseLayout from "../../../layouts/BaseLayout.astro";
-
\ No newline at end of file
+
diff --git a/src/pages/pl/for-founders.astro b/src/pages/pl/for-founders.astro
index e0f14c4..82bab7d 100644
--- a/src/pages/pl/for-founders.astro
+++ b/src/pages/pl/for-founders.astro
@@ -4,6 +4,7 @@ import BaseLayout from "../../layouts/BaseLayout.astro";
@@ -121,4 +122,4 @@ import BaseLayout from "../../layouts/BaseLayout.astro";
-
\ No newline at end of file
+
diff --git a/src/pages/pl/how-we-work.astro b/src/pages/pl/how-we-work.astro
index f0204e6..e2eddb4 100644
--- a/src/pages/pl/how-we-work.astro
+++ b/src/pages/pl/how-we-work.astro
@@ -4,6 +4,7 @@ import BaseLayout from "../../layouts/BaseLayout.astro";
@@ -96,4 +97,4 @@ import BaseLayout from "../../layouts/BaseLayout.astro";
-
\ No newline at end of file
+
diff --git a/src/pages/pl/index.astro b/src/pages/pl/index.astro
index e0d5964..37c846c 100644
--- a/src/pages/pl/index.astro
+++ b/src/pages/pl/index.astro
@@ -6,6 +6,7 @@ import HeroVisual from "../../components/HeroVisual.astro";
@@ -212,4 +213,4 @@ import HeroVisual from "../../components/HeroVisual.astro";
-
\ No newline at end of file
+
diff --git a/src/pages/pl/kontakt.astro b/src/pages/pl/kontakt.astro
index a658f7a..b9ae900 100644
--- a/src/pages/pl/kontakt.astro
+++ b/src/pages/pl/kontakt.astro
@@ -4,6 +4,7 @@ import BaseLayout from "../../layouts/BaseLayout.astro";
@@ -138,4 +139,4 @@ import BaseLayout from "../../layouts/BaseLayout.astro";
showTick();
};
-
\ No newline at end of file
+
diff --git a/src/pages/pl/oferta/index.astro b/src/pages/pl/oferta/index.astro
index cba8580..6d4959d 100644
--- a/src/pages/pl/oferta/index.astro
+++ b/src/pages/pl/oferta/index.astro
@@ -4,6 +4,7 @@ import BaseLayout from "../../../layouts/BaseLayout.astro";
@@ -107,4 +108,4 @@ import BaseLayout from "../../../layouts/BaseLayout.astro";
-
\ No newline at end of file
+
diff --git a/src/pages/pl/oferta/infrastruktura/index.astro b/src/pages/pl/oferta/infrastruktura/index.astro
index c0f0528..19ccd01 100644
--- a/src/pages/pl/oferta/infrastruktura/index.astro
+++ b/src/pages/pl/oferta/infrastruktura/index.astro
@@ -2,7 +2,7 @@
import BaseLayout from "../../../../layouts/BaseLayout.astro";
---
-
+
Infrastruktura
@@ -44,4 +44,4 @@ import BaseLayout from "../../../../layouts/BaseLayout.astro";
-
\ No newline at end of file
+
diff --git a/src/pages/pl/oferta/obsluga/index.astro b/src/pages/pl/oferta/obsluga/index.astro
index 8d19af7..5b26b5c 100644
--- a/src/pages/pl/oferta/obsluga/index.astro
+++ b/src/pages/pl/oferta/obsluga/index.astro
@@ -2,7 +2,7 @@
import BaseLayout from "../../../../layouts/BaseLayout.astro";
---
-
+
Obsługa po wdrożeniu
@@ -59,4 +59,4 @@ import BaseLayout from "../../../../layouts/BaseLayout.astro";
-
\ No newline at end of file
+
diff --git a/src/pages/pl/oferta/programowanie/index.astro b/src/pages/pl/oferta/programowanie/index.astro
index 2dafa8d..bb69d45 100644
--- a/src/pages/pl/oferta/programowanie/index.astro
+++ b/src/pages/pl/oferta/programowanie/index.astro
@@ -2,7 +2,7 @@
import BaseLayout from "../../../../layouts/BaseLayout.astro";
---
-
+
Programowanie
@@ -45,4 +45,4 @@ import BaseLayout from "../../../../layouts/BaseLayout.astro";
-
\ No newline at end of file
+
diff --git a/src/pages/pl/oferta/projektowanie/index.astro b/src/pages/pl/oferta/projektowanie/index.astro
index dd836b3..13493dc 100644
--- a/src/pages/pl/oferta/projektowanie/index.astro
+++ b/src/pages/pl/oferta/projektowanie/index.astro
@@ -2,7 +2,7 @@
import BaseLayout from "../../../../layouts/BaseLayout.astro";
---
-
+
Projektowanie
@@ -45,4 +45,4 @@ import BaseLayout from "../../../../layouts/BaseLayout.astro";
-
\ No newline at end of file
+
diff --git a/src/pages/pl/oferta/wdrozenie/index.astro b/src/pages/pl/oferta/wdrozenie/index.astro
index 43b240e..eb43faa 100644
--- a/src/pages/pl/oferta/wdrozenie/index.astro
+++ b/src/pages/pl/oferta/wdrozenie/index.astro
@@ -2,7 +2,7 @@
import BaseLayout from "../../../../layouts/BaseLayout.astro";
---
-
+
Wdrożenie
@@ -41,4 +41,4 @@ import BaseLayout from "../../../../layouts/BaseLayout.astro";
-
\ No newline at end of file
+
From 4802cfa229e56a0933350b2320405ace8c03ff51 Mon Sep 17 00:00:00 2001
From: Don-Damiano <133017758+Don-Damiano@users.noreply.github.com>
Date: Thu, 29 Jan 2026 12:22:35 +0100
Subject: [PATCH 2/2] fix(i18n): guard missing route keys
---
src/layouts/BaseLayout.astro | 20 ++++++++++----------
src/layouts/CaseStudyLayout.astro | 20 ++++++++++++++++++--
2 files changed, 28 insertions(+), 12 deletions(-)
diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro
index 1b8ac68..45be38b 100644
--- a/src/layouts/BaseLayout.astro
+++ b/src/layouts/BaseLayout.astro
@@ -10,7 +10,7 @@ type Props = {
title?: string;
description?: string;
lang?: "pl" | "en";
- routeKey: RouteKey;
+ routeKey?: RouteKey;
routeParams?: RouteParams;
};
@@ -23,10 +23,10 @@ const {
} = Astro.props as Props;
const baseUrl = "https://rocketdeploy.dev";
-const { pl: plPath, en: enPath } = getRoutePaths(routeKey, routeParams);
-const plUrl = new URL(plPath, baseUrl).toString();
-const enUrl = new URL(enPath, baseUrl).toString();
-const canonicalUrl = lang === "pl" ? plUrl : enUrl;
+const routePaths = routeKey ? getRoutePaths(routeKey, routeParams) : null;
+const plUrl = routePaths ? new URL(routePaths.pl, baseUrl).toString() : null;
+const enUrl = routePaths ? new URL(routePaths.en, baseUrl).toString() : null;
+const canonicalUrl = routePaths ? (lang === "pl" ? plUrl : enUrl) : null;
---
@@ -42,16 +42,16 @@ const canonicalUrl = lang === "pl" ? plUrl : enUrl;
{description && }
{description && }
-
-
-
-
+ {canonicalUrl && }
+ {plUrl && }
+ {enUrl && }
+ {enUrl && }
diff --git a/src/layouts/CaseStudyLayout.astro b/src/layouts/CaseStudyLayout.astro
index a22b37e..4aebfd5 100644
--- a/src/layouts/CaseStudyLayout.astro
+++ b/src/layouts/CaseStudyLayout.astro
@@ -1,9 +1,25 @@
---
import BaseLayout from "./BaseLayout.astro";
-const { title, lang = "en", tags = [] } = Astro.props;
+import type { RouteKey, RouteParams } from "../i18n/routes";
+
+type Props = {
+ title: string;
+ lang?: "pl" | "en";
+ tags?: string[];
+ routeKey?: RouteKey;
+ routeParams?: RouteParams;
+};
+
+const {
+ title,
+ lang = "en",
+ tags = [],
+ routeKey,
+ routeParams,
+} = Astro.props as Props;
---
-
+