diff --git a/.gitignore b/.gitignore
index c2acf0d..f679a05 100644
--- a/.gitignore
+++ b/.gitignore
@@ -40,5 +40,5 @@ temp/
# Public generated
public/**/*.avif
-public/**/*.webp
+# public/**/*.webp
public/og/*.txt
diff --git a/package.json b/package.json
index 982c1a6..cd731f2 100644
--- a/package.json
+++ b/package.json
@@ -13,6 +13,7 @@
"@preact/signals": "^2.5.1",
"astro": "^5.16.0",
"js-yaml": "^4.1.0",
+ "marked": "^17.0.1",
"preact": "^10.27.2"
},
"devDependencies": {
diff --git a/public/images/fiber2.webp b/public/images/fiber2.webp
new file mode 100644
index 0000000..5d4c5cf
Binary files /dev/null and b/public/images/fiber2.webp differ
diff --git a/public/images/section-fiber.webp b/public/images/section-fiber.webp
new file mode 100644
index 0000000..b1fb6d1
Binary files /dev/null and b/public/images/section-fiber.webp differ
diff --git a/public/images/section-phone.webp b/public/images/section-phone.webp
new file mode 100644
index 0000000..fc688d7
Binary files /dev/null and b/public/images/section-phone.webp differ
diff --git a/public/images/section-radiowy.webp b/public/images/section-radiowy.webp
new file mode 100644
index 0000000..04aed08
Binary files /dev/null and b/public/images/section-radiowy.webp differ
diff --git a/public/images/section-tv.webp b/public/images/section-tv.webp
new file mode 100644
index 0000000..b7b73d1
Binary files /dev/null and b/public/images/section-tv.webp differ
diff --git a/src/components/sections/SectionDefault.astro b/src/components/sections/SectionDefault.astro
new file mode 100644
index 0000000..29e023b
--- /dev/null
+++ b/src/components/sections/SectionDefault.astro
@@ -0,0 +1,36 @@
+---
+import Markdown from "../../islands/Markdown.jsx";
+
+const { section, index } = Astro.props;
+
+const hasImage = !!section.image;
+const reverse = index % 2 === 1;
+---
+
+
+
+ {hasImage && (
+

+ )}
+
+
+
{section.title}
+
+
+
+ {section.button && (
+
+ )}
+
+
+
+
diff --git a/src/components/sections/SectionIframeChannels.astro b/src/components/sections/SectionIframeChannels.astro
new file mode 100644
index 0000000..2d51f33
--- /dev/null
+++ b/src/components/sections/SectionIframeChannels.astro
@@ -0,0 +1,20 @@
+---
+import IframeChannelSwitcher from "../../islands/ChannelSwitcher.jsx";
+
+const { section } = Astro.props;
+---
+
+
+
+ {section.title && (
+
{section.title}
+ )}
+
+ {section.content && (
+
+ )}
+
+
+
+
+
diff --git a/src/components/sections/SectionRenderer.astro b/src/components/sections/SectionRenderer.astro
new file mode 100644
index 0000000..41ca346
--- /dev/null
+++ b/src/components/sections/SectionRenderer.astro
@@ -0,0 +1,29 @@
+---
+import yaml from "js-yaml";
+import fs from "fs";
+import { marked } from "marked";
+
+import SectionDefault from "./SectionDefault.astro";
+import SectionIframeChannels from "./SectionIframeChannels.astro";
+
+const { src } = Astro.props;
+
+// Load YAML
+const data = yaml.load(fs.readFileSync(src, "utf8")) ?? { sections: [] };
+
+// Markdown → HTML
+const sections = (data.sections as any[]).map((s: any) => ({
+ ...s,
+ html: marked(s.content || "")
+}));
+---
+
+{sections.map((section: any, index: number) => {
+ const type = section.type || "default";
+
+ if (type === "iframe-channels") {
+ return ;
+ }
+
+ return ;
+})}
diff --git a/src/content/site/site.section.yaml b/src/content/site/site.section.yaml
index 4dde582..f340eeb 100644
--- a/src/content/site/site.section.yaml
+++ b/src/content/site/site.section.yaml
@@ -1,7 +1,8 @@
sections:
- title: "Internet Światłowodowy"
- image: "/images/section-fiber.jpg"
+ image: "/images/section-fiber.webp"
dimmed: true
+ type: default
button:
text: "Zobacz ofertę →"
url: "/internet-swiatlowod/"
@@ -10,13 +11,36 @@ sections:
Odkryj komfort technologii stworzonej do pracy, rozrywki i życia bez ograniczeń.
- - title: "Internet Radiowy"
- image: "/images/section-radiowy.jpg"
+ - title: "Internet i Telewizja"
+ image: "/images/section-tv.webp"
dimmed: true
+ button:
+ text: "Zobacz ofertę →"
+ url: "/internet-telewizja/"
+ content: |
+ Internet + TV to połączenie stabilnego, szybkiego łącza z bogatą ofertą telewizyjną dla całej rodziny.
+
+ Korzystaj z internetu bez limitów i oglądaj swoje ulubione programy w perfekcyjnej jakości — w jednym prostym pakiecie.
+
+ - title: "Internet Radiowy"
+ image: "/images/section-radiowy.webp"
+ dimmed: true
+ type: default
button:
text: "Zobacz ofertę →"
url: "/internet-radiowy/"
content: |
Nowoczesna technologia radiowa gwarantuje stabilny internet o wysokiej wydajności tam, gdzie inne łącza nie mają szans.
- To szybki start w świat cyfrowej pracy i rozrywki — bez konieczności instalacji kabli.
\ No newline at end of file
+ To szybki start w świat cyfrowej pracy i rozrywki — bez konieczności instalacji kabli.
+
+ - title: "Telefon"
+ image: "/images/section-phone.webp"
+ dimmed: true
+ button:
+ text: "Zobacz ofertę →"
+ url: "/internet-telewizja/"
+ content: |
+ Nasza telefonia wykorzystuje zaawansowaną technologię VoIP, dzięki której dźwięk jest wyraźny, a połączenia stabilne.
+
+ To idealne rozwiązanie dla domu i firm, które potrzebują jakości i przewidywalnych kosztów.
\ No newline at end of file
diff --git a/src/islands/ChannelSwitcher.jsx b/src/islands/ChannelSwitcher.jsx
new file mode 100644
index 0000000..5ddb7c4
--- /dev/null
+++ b/src/islands/ChannelSwitcher.jsx
@@ -0,0 +1,39 @@
+import { useState } from "preact/hooks";
+
+export default function ChannelSwitcher({ sets = [] }) {
+ const [activeId, setActiveId] = useState(sets[0]?.id);
+
+ const active = sets.find((x) => x.id === activeId);
+ const iframeSrc = `https://www.jambox.pl/iframe-pakiet-logo?p=${active?.p}`;
+
+ return (
+
+
+
+ {sets.map((s) => (
+
+ ))}
+
+
+
+ {/* 🔹 Iframe */}
+
+
+
+ );
+}
diff --git a/src/islands/Markdown.jsx b/src/islands/Markdown.jsx
new file mode 100644
index 0000000..1f301fb
--- /dev/null
+++ b/src/islands/Markdown.jsx
@@ -0,0 +1,63 @@
+import { marked } from "marked";
+
+marked.setOptions({
+ gfm: true,
+ breaks: true,
+ headerIds: false,
+ mangle: false,
+ sanitize: false,
+ smartLists: true,
+ smartypants: false,
+});
+
+
+function applyShortcodes(md, ctx = {}) {
+ md = md.replace(/{{\s*channels\s*}}/g, () => {
+ if (!ctx.kanaly) return "";
+
+ const html = ctx.kanaly
+ .map(
+ (k) => `
+
+

+
+`
+ )
+ .join("");
+
+ return `
+
+ ${html}
+
+`;
+ });
+
+ return md;
+}
+
+export default function FuzMarkdown({ text, ctx = {} }) {
+ if (!text) return null;
+
+
+ let processed = applyShortcodes(text, ctx);
+
+ // Konwersja kinków na modal linki
+ processed = processed.replace(
+ /\[([^\]]+)\]\(#([^)]+)\)/g,
+ `$1`
+ );
+
+ const html = marked(processed);
+
+ return (
+
+ );
+}
diff --git a/src/pages/index.astro b/src/pages/index.astro
index 5302d8b..7939d6e 100644
--- a/src/pages/index.astro
+++ b/src/pages/index.astro
@@ -1,6 +1,7 @@
---
import DefaultLayout from "../layouts/DefaultLayout.astro";
import Hero from "../components/hero/Hero.astro";
+import SectionRenderer from "../components/sections/SectionRenderer.astro"
import yaml from "js-yaml";
import fs from "fs";
@@ -11,4 +12,5 @@ const hero = yaml.load(fs.readFileSync("./src/content/home/hero.yaml", "utf8"));
+
diff --git a/src/styles/base.css b/src/styles/base.css
index 1ae1f61..dffbbb5 100644
--- a/src/styles/base.css
+++ b/src/styles/base.css
@@ -2,4 +2,6 @@
@import "./theme.css";
@import "./navbar.css";
@import "./hero.css";
-@import "./buttons.css";
\ No newline at end of file
+@import "./buttons.css";
+@import "./sections.css";
+@import "./markdown.css";
\ No newline at end of file
diff --git a/src/styles/markdown.css b/src/styles/markdown.css
new file mode 100644
index 0000000..21b412c
--- /dev/null
+++ b/src/styles/markdown.css
@@ -0,0 +1,45 @@
+.fuz-markdown {
+ @apply leading-relaxed text-base md:text-lg;
+
+ /* odstępy między elementami */
+}
+
+.fuz-markdown p {
+ @apply mb-4 text-3xl;
+}
+
+.fuz-markdown h1 {
+ @apply text-3xl font-bold mt-8 mb-4;
+}
+
+.fuz-markdown h2 {
+ @apply text-2xl font-semibold mt-6 mb-3;
+}
+
+.fuz-markdown h3 {
+ @apply text-xl font-semibold mt-4 mb-2;
+}
+
+.fuz-markdown ul {
+ @apply list-disc pl-6 mb-4;
+}
+
+.fuz-markdown ol {
+ @apply list-decimal pl-6 mb-4;
+}
+
+.fuz-markdown li {
+ @apply mb-1;
+}
+
+.fuz-markdown a {
+ @apply text-blue-600 dark:text-blue-400 underline hover:no-underline;
+}
+
+.fuz-markdown blockquote {
+ @apply border-l-4 border-gray-300 dark:border-gray-700 pl-4 italic mb-4;
+}
+
+.fuz-markdown strong {
+ @apply font-semibold;
+}
diff --git a/src/styles/sections.css b/src/styles/sections.css
new file mode 100644
index 0000000..500b7d5
--- /dev/null
+++ b/src/styles/sections.css
@@ -0,0 +1,23 @@
+.fuz-section {
+ @apply py-20 px-6;
+}
+
+.fuz-section-grid {
+ @apply grid items-center gap-10 max-w-7xl mx-auto;
+}
+
+.fuz-section-image {
+ @apply w-full h-full object-cover ;
+}
+
+.fuz-image-dimmed {
+ opacity: 0.75;
+}
+
+.fuz-section-title {
+ @apply text-5xl md:text-5xl font-bold mb-6;
+}
+
+.fuz-section-text {
+ @apply max-w-4xl mx-auto;
+}