diff --git a/src/components/ui/Background.astro b/src/components/ui/Background.astro
new file mode 100644
index 0000000..0032b2f
--- /dev/null
+++ b/src/components/ui/Background.astro
@@ -0,0 +1,7 @@
+---
+const { isDark = false } = Astro.props;
+---
+
+
+
+
diff --git a/src/components/ui/CTA.astro b/src/components/ui/CTA.astro
new file mode 100644
index 0000000..bfab9f8
--- /dev/null
+++ b/src/components/ui/CTA.astro
@@ -0,0 +1,38 @@
+---
+import { Icon } from "astro-icon/components";
+import type { CallToAction } from "~/types";
+
+const { callToAction } = Astro.props;
+
+const {
+ targetBlank,
+ text = "",
+ icon = "",
+ href = "",
+} = callToAction as CallToAction;
+---
+
+
diff --git a/src/components/ui/Headline.astro b/src/components/ui/Headline.astro
new file mode 100644
index 0000000..3e37ed1
--- /dev/null
+++ b/src/components/ui/Headline.astro
@@ -0,0 +1,48 @@
+---
+import type { Headline } from "~/types";
+import { twMerge } from "tailwind-merge";
+
+const {
+ title = await Astro.slots.render("title"),
+ subtitle = await Astro.slots.render("subtitle"),
+ tagline,
+ classes = {},
+} = Astro.props as Headline;
+
+const {
+ container: containerClass = "max-w-3xl",
+ title: titleClass = "text-3xl md:text-4xl ",
+ subtitle: subtitleClass = "text-xl",
+} = classes;
+---
+
+{
+ (title || subtitle || tagline) && (
+
+ {tagline && (
+
+ )}
+ {title && (
+
+ )}
+
+ {subtitle && (
+
+ )}
+
+ )
+}
diff --git a/src/components/ui/ItemGrid.astro b/src/components/ui/ItemGrid.astro
new file mode 100644
index 0000000..c51c734
--- /dev/null
+++ b/src/components/ui/ItemGrid.astro
@@ -0,0 +1,100 @@
+---
+import { Icon } from "astro-icon/components";
+import { twMerge } from "tailwind-merge";
+import type { ItemGrid } from "~/types";
+import CTA from "./CTA.astro";
+
+const {
+ items = [],
+ columns,
+ defaultIcon = "",
+ classes = {},
+} = Astro.props as ItemGrid;
+
+const {
+ container: containerClass = "",
+ // container: containerClass = "md:grid-cols-2",
+ panel: panelClass = "",
+ title: titleClass = "",
+ description: descriptionClass = "",
+ icon: defaultIconClass = "text-primary",
+} = classes;
+---
+
+{
+ items && (
+
+ {items.map(
+ ({
+ title,
+ description,
+ icon,
+ callToAction,
+ classes: itemClasses = {},
+ }) => (
+
+
+
+ {(icon || defaultIcon) && (
+
+ )}
+
+
+
+ {title}
+
+ {description && (
+
+ )}
+ {callToAction && (
+
+
+
+ )}
+
+
+
+ )
+ )}
+
+ )
+}
diff --git a/src/components/ui/ItemGrid2.astro b/src/components/ui/ItemGrid2.astro
new file mode 100644
index 0000000..9511413
--- /dev/null
+++ b/src/components/ui/ItemGrid2.astro
@@ -0,0 +1,94 @@
+---
+import { Icon } from "astro-icon/components";
+import { twMerge } from "tailwind-merge";
+import type { ItemGrid } from "~/types";
+import CTA from "./CTA.astro";
+
+const {
+ items = [],
+ columns,
+ defaultIcon = "",
+ classes = {},
+} = Astro.props as ItemGrid;
+
+const {
+ container: containerClass = "",
+ // container: containerClass = "sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-3",
+ panel: panelClass = "",
+ title: titleClass = "",
+ description: descriptionClass = "",
+ icon: defaultIconClass = "text-primary",
+} = classes;
+---
+
+{
+ items && (
+
+ {items.map(
+ ({
+ title,
+ description,
+ icon,
+ callToAction,
+ classes: itemClasses = {},
+ }) => (
+
+ {(icon || defaultIcon) && (
+
+ )}
+
+ {title}
+
+ {description && (
+
+ )}
+ {callToAction && (
+
+
+
+ )}
+
+ )
+ )}
+
+ )
+}
diff --git a/src/components/ui/Timeline.astro b/src/components/ui/Timeline.astro
new file mode 100644
index 0000000..df655d1
--- /dev/null
+++ b/src/components/ui/Timeline.astro
@@ -0,0 +1,82 @@
+---
+import { Icon } from "astro-icon/components";
+import { twMerge } from "tailwind-merge";
+import type { Item } from "~/types";
+
+export interface Props {
+ items?: Array- ;
+ defaultIcon?: string;
+ classes?: Record;
+}
+
+const { items = [], classes = {}, defaultIcon } = Astro.props as Props;
+
+const {
+ container: containerClass = "",
+ panel: panelClass = "",
+ title: titleClass = "",
+ description: descriptionClass = "",
+ icon: defaultIconClass = "text-primary dark:text-slate-200 border-primary dark:border-blue-700",
+} = classes;
+---
+
+{
+ items && items.length && (
+
+ {items.map(
+ (
+ { title, description, icon, classes: itemClasses = {} },
+ index = 0
+ ) => (
+
+
+
+
+ {(icon || defaultIcon) && (
+
+ )}
+
+
+ {index !== items.length - 1 && (
+
+ )}
+
+
+ {title && (
+
+ )}
+ {description && (
+
+ )}
+
+
+ )
+ )}
+
+ )
+}
diff --git a/src/components/ui/WidgetWrapper.astro b/src/components/ui/WidgetWrapper.astro
new file mode 100644
index 0000000..a4cc5c5
--- /dev/null
+++ b/src/components/ui/WidgetWrapper.astro
@@ -0,0 +1,24 @@
+---
+import { twMerge } from "tailwind-merge";
+import Background from "./Background.astro";
+
+const { id, isDark = false, containerClass = "", bg, as = "section" } = Astro.props;
+
+const WrapperTag = as;
+---
+
+
+
+
+ {bg ? : }
+
+
+
+
+
+