diff --git a/assets/css/main.css b/assets/css/main.css
index e2631b7..91251cf 100644
--- a/assets/css/main.css
+++ b/assets/css/main.css
@@ -35,6 +35,7 @@
@media (max-width: 499px) {
:root {
--text-font-size: 18px;
+ --small-text-font-size: 16px;
--4-cols: 100%;
}
}
@@ -483,6 +484,107 @@ footer .icon {
}
}
+.community {
+ height: 380px;
+ margin-top: -1rem;
+}
+
+.community_container {
+ position: absolute;
+ left: 0;
+ right: 0;
+ display: flex;
+ justify-content: center;
+}
+.community_page_left,
+.community_page_right {
+ background: none;
+ position: absolute;
+ top: 0;
+ border: 0;
+ padding: 0.5rem 1rem;
+ color: var(--text-color);
+ cursor: pointer;
+}
+
+.community_page_left:hover,
+.community_page_right:hover {
+ color: var(--accent-color);
+}
+
+.community_page_left {
+ left: 0;
+}
+
+.community_page_right {
+ right: 0;
+}
+
+.community_inner {
+ max-width: 100%;
+ overflow-x: auto;
+ display: flex;
+ flex-wrap: nowrap;
+ padding: 2.5rem 1rem 0;
+ gap: 2rem;
+ scroll-behavior: smooth;
+}
+
+.community-entry {
+ display: block;
+}
+
+.community-entry__imgs {
+ position: relative;
+ width: 300px;
+ height: 240px;
+ transition: opacity 250ms linear;
+ border-radius: 30px;
+ overflow: hidden;
+}
+
+.community-entry__person,
+.community-entry__diagram {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 300px;
+ height: 240px;
+ border-radius: 30px;
+}
+
+.community-entry__diagram,
+.community--tech .community-entry:hover .community-entry__diagram {
+ transform: scale(1.05);
+ opacity: 0;
+ transition: transform 400ms ease-in-out, opacity 400ms ease-in-out;
+ box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.5);
+}
+
+.community-entry:hover .community-entry__diagram,
+.community--tech .community-entry__diagram {
+ transform: scale(1);
+ opacity: 1;
+}
+
+.community-entry p {
+ width: 100%;
+ margin: 1rem 0 0.5rem;
+ padding: 0;
+ text-align: center;
+ color: var(--text-color);
+ font-size: var(--small-text-font-size);
+ text-decoration: underline;
+}
+
+.community-entry:hover p {
+ color: var(--accent-color);
+}
+
+.community-selected {
+ text-decoration: underline;
+}
+
.sponsors {
margin-bottom: 2em;
}
diff --git a/assets/js/main.js b/assets/js/main.js
index 13b36f4..2073796 100644
--- a/assets/js/main.js
+++ b/assets/js/main.js
@@ -29,3 +29,54 @@ document
target.scrollIntoView({ behavior: "smooth" });
});
});
+
+// community slider controls
+const $community = document.querySelector(".community_container");
+const $communityInner = document.querySelector(".community_inner");
+const $communityLeft = document.querySelector(".community_page_left");
+const $communityRight = document.querySelector(".community_page_right");
+const $personLink = document.querySelector("a[href$='#community-person']");
+const $techLink = document.querySelector("a[href$='#community-tech']");
+if ($community) {
+ const updateButtonVisibility = () => {
+ const scrollLeft = $communityInner.scrollLeft;
+ const maxScrollLeft =
+ $communityInner.scrollWidth - $communityInner.clientWidth;
+
+ $communityLeft.style.display = scrollLeft > 0 ? "block" : "none";
+ $communityRight.style.display =
+ scrollLeft < maxScrollLeft ? "block" : "none";
+ };
+
+ const scrollBy = 330;
+
+ $communityLeft.addEventListener("click", () => {
+ const current = $communityInner.scrollLeft;
+ const left = Math.max(0, current - scrollBy);
+ $communityInner.scrollTo({ left, behavior: "smooth" });
+ });
+
+ $communityRight.addEventListener("click", () => {
+ const current = $communityInner.scrollLeft;
+ const max = $communityInner.scrollWidth;
+ const left = Math.min(max, current + scrollBy);
+ $communityInner.scrollTo({ left, behavior: "smooth" });
+ });
+
+ $communityInner.addEventListener("scroll", updateButtonVisibility);
+ window.addEventListener("resize", updateButtonVisibility);
+
+ updateButtonVisibility();
+
+ $personLink.addEventListener("click", () => {
+ $community.classList.remove("community--tech");
+ $personLink.classList.add("community-selected");
+ $techLink.classList.remove("community-selected");
+ });
+ $techLink.addEventListener("click", () => {
+ $community.classList.add("community--tech");
+ $techLink.classList.add("community-selected");
+ $personLink.classList.remove("community-selected");
+ });
+ $personLink.classList.add("community-selected");
+}
diff --git a/content/_index.de.md b/content/_index.de.md
index f7fc4b0..9b05e61 100644
--- a/content/_index.de.md
+++ b/content/_index.de.md
@@ -102,6 +102,22 @@ Du hast ein spezielles Setup oder verwendest exotische Geräte? evcc kommt mit e
Zudem gibt es Integrationen für Home Assistant, openHAB und ioBroker.
Um sich auch mit anderen, übergeordneten Energiemanagern abzusprechen, hat evcc zusätzlich eine Unterstützung der Protokolle SEMP und EEBUS integriert.
+---
+
+## Community Porträts
+
+In unserem [Blog](https://docs.evcc.io/blog) stellen wir regelmäßig evcc Installationen aus der Community vor. Hier bekommst du einen Einblick über die [Menschen](#community-person) und ihre [Technik](#community-tech).
+
+{{< community >}}
+{{< community-entry img="andreas" name="Andreas aus Wettringen" link="https://docs.evcc.io/blog/2024/11/14/andreas-aus-wettringen">}}
+{{< community-entry img="bastian" name="Bastian aus Ahlhorn" link="https://docs.evcc.io/blog/2024/10/25/portrait-bastian-aus-alhorn">}}
+{{< community-entry img="tjarko" name="Tjarko aus Großefehn" link="https://docs.evcc.io/blog/2024/09/21/portrait-tjarko-grossefehn">}}
+{{< community-entry img="christian" name="Christian aus Trebbin" link="https://docs.evcc.io/blog/2024/08/25/portrait-christian-trebbin">}}
+{{< community-entry img="arne" name="Arne aus Gifhorn" link="https://docs.evcc.io/blog/2024/08/09/portrait-arne-gifhorn">}}
+{{< /community >}}
+
+---
+
## Wie evcc funktioniert
{{< full_width_image src="/img/evcc-schema.svg" alt="Darstellung der Funktionsweise" width="200" height="100" >}}
diff --git a/content/_index.en.md b/content/_index.en.md
index d168cae..c0e64c6 100644
--- a/content/_index.en.md
+++ b/content/_index.en.md
@@ -101,6 +101,22 @@ You have a special setup or use exotic devices? evcc comes with a **flexible plu
Already have a smart home system? We integrate nicely with Home Assistant, openHAB and ioBroker. evcc even works with higher-level energy managers and can take commands via SEMP and EEBUS protocol.
+---
+
+## Community Portraits
+
+In our [blog](https://docs.evcc.io/en/blog) we regularly present evcc installations from the community. Here you get an insight into the [people](#community-person) and their [technology](#community-tech).
+
+{{< community >}}
+{{< community-entry img="andreas" name="Andreas from Wettringen" link="https://docs.evcc.io/en/blog/2024/11/14/andreas-aus-wettringen">}}
+{{< community-entry img="bastian" name="Bastian from Ahlhorn" link="https://docs.evcc.io/en/blog/2024/10/25/portrait-bastian-aus-alhorn">}}
+{{< community-entry img="tjarko" name="Tjarko from Großefehn" link="https://docs.evcc.io/en/blog/2024/09/21/portrait-tjarko-grossefehn">}}
+{{< community-entry img="christian" name="Christian from Trebbin" link="https://docs.evcc.io/en/blog/2024/08/25/portrait-christian-trebbin">}}
+{{< community-entry img="arne" name="Arne from Gifhorn" link="https://docs.evcc.io/en/blog/2024/08/09/portrait-arne-gifhorn">}}
+{{< /community >}}
+
+---
+
## How evcc works
{{< full_width_image src="/img/evcc-schema.svg" alt="How it works" width="200" height="100" >}}
diff --git a/layouts/shortcodes/community-entry.html b/layouts/shortcodes/community-entry.html
new file mode 100644
index 0000000..c4de3e9
--- /dev/null
+++ b/layouts/shortcodes/community-entry.html
@@ -0,0 +1,14 @@
+{{- $img := .Get "img" -}}
+{{- $title := .Get "title" -}}
+{{- $name := .Get "name" -}}
+{{- $link := .Get "link" -}}
+
+ {{ $name }} {{ $title }}