diff --git a/public/android-chrome-192x192.png b/public/android-chrome-192x192.png new file mode 100644 index 0000000..bbfc609 Binary files /dev/null and b/public/android-chrome-192x192.png differ diff --git a/public/android-chrome-512x512.png b/public/android-chrome-512x512.png new file mode 100644 index 0000000..f77a304 Binary files /dev/null and b/public/android-chrome-512x512.png differ diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png new file mode 100644 index 0000000..ed1ff81 Binary files /dev/null and b/public/apple-touch-icon.png differ diff --git a/public/browserconfig.xml b/public/browserconfig.xml new file mode 100644 index 0000000..b3930d0 --- /dev/null +++ b/public/browserconfig.xml @@ -0,0 +1,9 @@ + + + + + + #da532c + + + diff --git a/public/favicon-16x16.png b/public/favicon-16x16.png new file mode 100644 index 0000000..fde2aa6 Binary files /dev/null and b/public/favicon-16x16.png differ diff --git a/public/favicon-32x32.png b/public/favicon-32x32.png new file mode 100644 index 0000000..96fef57 Binary files /dev/null and b/public/favicon-32x32.png differ diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..3ba44ac Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/og/dokumenty-og.png b/public/og/dokumenty-og.png new file mode 100644 index 0000000..4da2977 Binary files /dev/null and b/public/og/dokumenty-og.png differ diff --git a/public/og/kontakt-og.png b/public/og/kontakt-og.png new file mode 100644 index 0000000..4da2977 Binary files /dev/null and b/public/og/kontakt-og.png differ diff --git a/public/site.webmanifest b/public/site.webmanifest new file mode 100644 index 0000000..d1b7fcd --- /dev/null +++ b/public/site.webmanifest @@ -0,0 +1,19 @@ +{ + "name": "FUZ Adam Rojek - Internet Światłowodowy", + "short_name": "FUZ", + "icons": [ + { + "src": "/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +} diff --git a/src/components/hero/Hero.astro b/src/components/hero/Hero.astro index ea2df7a..f85a712 100644 --- a/src/components/hero/Hero.astro +++ b/src/components/hero/Hero.astro @@ -1,6 +1,7 @@ --- import { Image, getImage } from "astro:assets"; import type { ImageMetadata } from "astro"; +import { stripImageExtension, findHeroImages } from "../../lib/astro-helpers"; interface CTA { label: string; @@ -26,21 +27,14 @@ const { ctas = [], } = Astro.props; -const imageBase = imageUrl.replace(/\.(webp|png|jpg|jpeg)$/i, ""); +const imageBase = stripImageExtension(imageUrl); const images = import.meta.glob<{ default: ImageMetadata }>( "/src/assets/hero/**/*.webp", { eager: true }, ); -function findImage(folder: string): ImageMetadata | null { - const key = `/src/assets/hero/${folder}/${imageBase}-${folder}.webp`; - return images[key]?.default ?? null; -} - -const mobile = findImage("mobile"); -const tablet = findImage("tablet"); -const desktop = findImage("desktop"); +const { mobile, tablet, desktop } = findHeroImages(images, imageBase); const mobileSet = mobile ? await getImage({ src: mobile, widths: [480, 640], format: "webp" }) @@ -122,4 +116,4 @@ const desktopImg = desktop )} - + \ No newline at end of file diff --git a/src/components/layout/Footer.astro b/src/components/layout/Footer.astro index c002a32..4a451f6 100644 --- a/src/components/layout/Footer.astro +++ b/src/components/layout/Footer.astro @@ -1,10 +1,7 @@ --- -import yaml from "js-yaml"; -import fs from "fs"; +import { loadYaml } from "../../lib/astro-helpers"; -const footer = yaml.load( - fs.readFileSync("./src/content/site/footer.yaml", "utf8"), -); +const footer = loadYaml("./src/content/site/footer.yaml"); --- + \ No newline at end of file diff --git a/src/components/layout/Header.astro b/src/components/layout/Header.astro index f5e9cd0..8a88d51 100644 --- a/src/components/layout/Header.astro +++ b/src/components/layout/Header.astro @@ -49,4 +49,4 @@ const links = [ - + \ No newline at end of file diff --git a/src/components/maps/CitiesList.astro b/src/components/maps/CitiesList.astro index 1a6f24a..73849e0 100644 --- a/src/components/maps/CitiesList.astro +++ b/src/components/maps/CitiesList.astro @@ -39,4 +39,4 @@ const sorted = cities.sort((a: string, b: any) => a.localeCompare(b, "pl")); .fuz-city-item { color: var(--f-text); } - + \ No newline at end of file diff --git a/src/components/maps/MapGoogle.astro b/src/components/maps/MapGoogle.astro index 3b83b2b..2a54006 100644 --- a/src/components/maps/MapGoogle.astro +++ b/src/components/maps/MapGoogle.astro @@ -47,7 +47,6 @@ const domId = `fuz-map-${Math.random().toString(36).slice(2)}`; script.defer = true; script.onerror = () => reject("Google Maps API failed to load"); - // Czekamy na google.maps.importLibrary script.onload = () => { const checkReady = () => { if (window.google?.maps?.importLibrary) { diff --git a/src/components/sections/SectionChannelsSearch.astro b/src/components/sections/SectionChannelsSearch.astro index 8c5b414..a9cf45b 100644 --- a/src/components/sections/SectionChannelsSearch.astro +++ b/src/components/sections/SectionChannelsSearch.astro @@ -24,4 +24,4 @@ const section = props.section ?? {}; - + \ No newline at end of file diff --git a/src/components/sections/SectionDefault.astro b/src/components/sections/SectionDefault.astro index 96123ba..0fb0aef 100644 --- a/src/components/sections/SectionDefault.astro +++ b/src/components/sections/SectionDefault.astro @@ -2,6 +2,7 @@ import { Image } from "astro:assets"; import type { ImageMetadata } from "astro"; import Markdown from "../../islands/Markdown.jsx"; +import { findSectionImage } from "../../lib/astro-helpers"; const { section, index } = Astro.props; @@ -13,15 +14,8 @@ const sectionImages = import.meta.glob<{ default: ImageMetadata }>( { eager: true }, ); -let sectionImage: ImageMetadata | null = null; - -if (section.image) { - const path = `/src/assets/sections/${section.image}`; - const mod = sectionImages[path]; - if (mod) sectionImage = mod.default; -} - -const isAboveFold = index === 0; // możesz zmienić warunek jak chcesz +const sectionImage = section.image ? findSectionImage(sectionImages, section.image) : null; +const isAboveFold = index === 0; ---
@@ -63,4 +57,4 @@ const isAboveFold = index === 0; // możesz zmienić warunek jak chcesz } -
+ \ No newline at end of file diff --git a/src/components/sections/SectionRenderer.astro b/src/components/sections/SectionRenderer.astro index 7682394..ec56d72 100644 --- a/src/components/sections/SectionRenderer.astro +++ b/src/components/sections/SectionRenderer.astro @@ -1,23 +1,13 @@ --- -import yaml from "js-yaml"; -import fs from "fs"; -import { marked } from "marked"; - +import { loadYaml, processMarkdownSections } from "../../lib/astro-helpers"; import SectionDefault from "./SectionDefault.astro"; - const { src } = Astro.props; -const data = yaml.load(fs.readFileSync(src, "utf8")) ?? { sections: [] }; - -const sections = (data.sections as any[]).map((s: any) => ({ - ...s, - html: marked(s.content || "") -})); +const data = loadYaml(src) ?? { sections: [] }; +const sections = processMarkdownSections(data.sections as any[]); --- {sections.map((section: any, index: number) => { - const type = section.type || "default"; - return ; -})} +})} \ No newline at end of file diff --git a/src/components/ui/NoteAccordion.astro b/src/components/ui/NoteAccordion.astro new file mode 100644 index 0000000..e5498d8 --- /dev/null +++ b/src/components/ui/NoteAccordion.astro @@ -0,0 +1,44 @@ +--- +type Props = { + text?: string; + star?: boolean; + className?: string; +}; + +const { text = "", star = true, className = "" } = Astro.props; + +const lines = String(text || "") + .replace(/\r\n/g, "\n") + .split("\n") + .map((l) => l.trim()); + +// usuń puste linie na początku/końcu +while (lines.length && !lines[0]) lines.shift(); +while (lines.length && !lines[lines.length - 1]) lines.pop(); + +const title = lines[0] || ""; + +// 👉 reszta jako JEDEN ciąg +const body = lines + .slice(1) + .join(" ") + .replace(/\s+/g, " ") + .trim(); + +const hasBody = body.length > 0; +--- +{title && ( +
+ + {star && *} + {title} (Szczegóły po rozwinięciu) + {hasBody && } + + + {hasBody && ( +
+

{`${title} ${body}`}

+
+ )} +
+)} diff --git a/src/components/ui/OfferCard.jsx b/src/components/ui/OfferCard.jsx index cba0131..aac6f61 100644 --- a/src/components/ui/OfferCard.jsx +++ b/src/components/ui/OfferCard.jsx @@ -13,6 +13,7 @@ import { moneyWithLabel } from "../../lib/money.js"; * @param {Array} props.features - Lista cech [{label, value}] * @param {Array} props.actions - Lista akcji (przycisków) * @param {string} props.cardId - ID dla scrollowania (opcjonalne) + * @param {boolean} props.withStart - Czy wyświetlać gwaizdkę przy cenie */ export default function OfferCard({ card, @@ -22,7 +23,8 @@ export default function OfferCard({ cenaOpis, features = [], actions = [], - cardId = null + cardId = null, + withStart = true }) { const hasPrice = typeof price === 'number'; @@ -43,7 +45,7 @@ export default function OfferCard({
{hasPrice ? ( - <>{moneyWithLabel(price, cenaOpis, false)} + <>{moneyWithLabel(price, cenaOpis, false, withStart)} ) : ( Wybierz opcje )} diff --git a/src/content/contact/seo.yaml b/src/content/contact/seo.yaml index 168601b..5f6976f 100644 --- a/src/content/contact/seo.yaml +++ b/src/content/contact/seo.yaml @@ -1,30 +1,18 @@ -site: - name: "FUZ Kontakt" - description: "Skontaktuj się z nami. Stabilny i szybki internet w Wyszkowie i okolicach" - url: "https://www.fuz.pl" - lang: "pl" - -company: - name: "FUZ Adam Rojek" - phone: "+48 (29) 643 80 55" - email: "biuro@fuz.pl" - street: "ul. Świętojańska 46" - city: "Wyszków" - postal: "07-200" - country: "PL" - lat: 52.597385 - lon: 21.456797 - logo: "/logo.webp" - page: - title: "FUZ Kontakt" - description: "Szybki, stabilny internet światłowodowy w Wyszkowie. Lokalny operator, realny serwis, błyskawiczne wsparcie." - image: "/og/home-og.png" + title: "Kontakt - FUZ Adam Rojek | Internet Światłowodowy Wyszków" + description: "Skontaktuj się z FUZ - lokalny operator internetu światłowodowego w Wyszkowie. Biuro obsługi klienta, zgłoszenia awarii, umów instalację. Tel: 29 643 80 55" # ← 160 znaków + image: "/og/kontakt-og.png" url: "/kontakt" keywords: - - kontakt internet światłowodowy Wyszków - - internet Wyszków - - światłowód Wyszków - - internet światłowodowy Wyszków - - lokalny operator internetu Wyszków - schema: {} + - kontakt FUZ Wyszków + - biuro obsługi klienta FUZ + - infolinia internet światłowodowy + - zgłoszenie awarii internet Wyszków + - umów instalację światłowodu + - numer telefonu FUZ + - adres biura FUZ Wyszków + - email kontakt operator + - obsługa klienta Wyszków + - serwis techniczny FUZ + - godziny otwarcia biura + - dojazd do biura Wyszków \ No newline at end of file diff --git a/src/content/document/seo.yaml b/src/content/document/seo.yaml new file mode 100644 index 0000000..fa53404 --- /dev/null +++ b/src/content/document/seo.yaml @@ -0,0 +1,18 @@ +page: + title: "Dokumenty - FUZ Adam Rojek | Regulaminy i Umowy" + description: "Dokumenty FUZ: regulamin świadczenia usług, wzór umowy, cennik, polityka prywatności, warunki techniczne. Wszystkie dokumenty do pobrania w formacie PDF." + image: "/og/dokumenty-og.png" + url: "/dokumenty" + keywords: + - dokumenty FUZ Wyszków + - regulamin świadczenia usług internet + - wzór umowy internet światłowodowy + - cennik usług FUZ + - polityka prywatności operator + - warunki świadczenia usług światłowód + - regulamin internetu Wyszków + - ogólne warunki umowy FUZ + - tabela opłat internet + - karta usług telekomunikacyjnych + - dokumenty prawne operator + - instrukcja reklamacji internet \ No newline at end of file diff --git a/src/content/home/seo.yaml b/src/content/home/seo.yaml index 1f5cab7..ce06952 100644 --- a/src/content/home/seo.yaml +++ b/src/content/home/seo.yaml @@ -1,32 +1,19 @@ -site: - name: "FUZ Internet światłowodowy w Wyszkowie" - description: "Stabilny i szybki internet" - url: "https://www.fuz.pl" - lang: "pl" - -company: - name: "FUZ Adam Rojek" - phone: "+48 (29) 643 80 55" - email: "biuro@fuz.pl" - street: "ul. Świętojańska 46" - city: "Wyszków" - postal: "07-200" - country: "PL" - lat: 52.597385 - lon: 21.456797 - logo: "/logo.webp" - page: - title: "FUZ Internet światłowodowy w Wyszkowie" - description: "Szybki, stabilny internet światłowodowy w Wyszkowie. Lokalny operator, realny serwis, błyskawiczne wsparcie." + title: "FUZ Adam Rojek - Internet Światłowodowy Wyszków | Szybki i Stabilny" + description: "Internet światłowodowy w Wyszkowie i okolicach. Lokalny operator z doświadczeniem - stabilne łącze, profesjonalny serwis, konkurencyjne ceny. Sprawdź dostępność!" image: "/og/home-og.png" url: "/" keywords: - - internet Wyszków - - światłowód Wyszków - internet światłowodowy Wyszków - - lokalny operator internetu Wyszków + - światłowód Wyszków + - internet Wyszków + - lokalny operator internet Wyszków + - szybki internet Wyszków + - stabilny internet Wyszków - internet telewizja Wyszków - - internet światłowodowy telewizja Wyszków - - telefon Wyszków - schema: {} + - pakiety internet TV Wyszków + - internet telefon Wyszków + - FUZ Wyszków + - fiber internet Wyszków + - internet Rząśnik Pułtusk + - internet światłowodowy okolice Wyszkowa \ No newline at end of file diff --git a/src/content/internet-swiatlowodowy/cards.yaml b/src/content/internet-swiatlowodowy/cards.yaml index fd16053..68fff6c 100644 --- a/src/content/internet-swiatlowodowy/cards.yaml +++ b/src/content/internet-swiatlowodowy/cards.yaml @@ -1,12 +1,14 @@ tytul: Internet światłowodowy opis: | + Internet światłowodowy w Wyszkowie i okolicach Wybierz rodzaj budynku i czas trwania umowy uwaga: | - Powyższe „ceny brutto z Rabatami 15zł” uwzględniają rabat -15 zł (z czego -5 zł - Rabat za wyrażenie zgody na otrzymywanie Rachunków/faktur VAT za świadczone - przez Dostawcę Usług usługi telekomunikacyjne drogą elektroniczną na wskazany w umowie adres mail oraz za pośrednictwem EBOK; -10 zł - Rabat pod warunkiem - złożenia wniosku o dostarczanie przez Dostawcę Usług treści każdej proponowanej zmiany warunków Umowy, w tym określonych w Umowie, Informacjach Przedumownych oraz danych Dostawcy Usług (chyba że przepisy powszechnie obowiązującego prawa przewidują wyłącznie zawiadomienia poprzez publiczne ogłoszenie), jak - również kontaktowanie się ze mną w ramach procedur reklamacyjnych, w tym w szczególności przesłania odpowiedzi na reklamację, na podany w Umowie adres poczty - elektronicznej). + Powyższe „ceny brutto z Rabatami 15zł” + uwzględniają rabat -15 zł (z czego -5 zł - Rabat za wyrażenie zgody na otrzymywanie Rachunków/faktur VAT za świadczone + przez Dostawcę Usług usługi telekomunikacyjne drogą elektroniczną na wskazany w umowie adres mail oraz za pośrednictwem EBOK; -10 zł - Rabat pod warunkiem + złożenia wniosku o dostarczanie przez Dostawcę Usług treści każdej proponowanej zmiany warunków Umowy, w tym określonych w Umowie, Informacjach Przedumownych oraz danych Dostawcy Usług (chyba że przepisy powszechnie obowiązującego prawa przewidują wyłącznie zawiadomienia poprzez publiczne ogłoszenie), jak + również kontaktowanie się ze mną w ramach procedur reklamacyjnych, w tym w szczególności przesłania odpowiedzi na reklamację, na podany w Umowie adres poczty + elektronicznej). cena_opis: "zł/mies." cards: diff --git a/src/content/internet-swiatlowodowy/seo.yaml b/src/content/internet-swiatlowodowy/seo.yaml index 6e48a45..cc40957 100644 --- a/src/content/internet-swiatlowodowy/seo.yaml +++ b/src/content/internet-swiatlowodowy/seo.yaml @@ -1,29 +1,19 @@ -site: - name: "FUZ Internet światłowodowy w Wyszkowie" - description: "Stabilny i szybki internet w Wyszkowie i okolicach" - url: "https://www.fuz.pl" - lang: "pl" - -company: - name: "FUZ Adam Rojek" - phone: "+48 (29) 643 80 55" - email: "biuro@fuz.pl" - street: "ul. Świętojańska 46" - city: "Wyszków" - postal: "07-200" - country: "PL" - lat: 52.597385 - lon: 21.456797 - logo: "/logo.webp" - page: - title: "FUZ Internet światłowodowy w Wyszkowie" - description: "Szybki, stabilny internet światłowodowy w Wyszkowie. Lokalny operator, realny serwis, błyskawiczne wsparcie." - image: "/images/internet-og.webp" + title: "Internet Światłowodowy Wyszków - Szybkie Łącze bez Limitów | FUZ" + description: "Internet światłowodowy do 1 Gb/s w Wyszkowie. Bez limitów danych, stabilne połączenie, montaż w 48h. Lokalny operator z profesjonalnym serwisem. Sprawdź ceny!" + image: "/og/internet-og.png" url: "/internet-swiatlowodowy" keywords: - - internet Wyszków - - światłowód Wyszków - internet światłowodowy Wyszków - - lokalny operator internetu - schema: {} + - światłowód Wyszków + - szybki internet Wyszków + - internet bez limitu Wyszków + - internet światłowodowy cena Wyszków + - światłowód do domu Wyszków + - fiber internet Wyszków + - operator światłowodu Wyszków + - instalacja internetu Wyszków + - internet światłowodowy oferta + - stabilny internet Wyszków + - internet światłowodowy Rząśnik + - internet światłowodowy Pułtusk diff --git a/src/content/internet-telewizja/cards.yaml b/src/content/internet-telewizja/cards.yaml index 5147461..8e47899 100644 --- a/src/content/internet-telewizja/cards.yaml +++ b/src/content/internet-telewizja/cards.yaml @@ -2,7 +2,8 @@ tytul: "Internet z telewizją" opis: | Wybierz rodzaj budynku i czas trwania umowy uwaga: | - Powyższe „ceny brutto z Rabatami 15zł” uwzględniają rabat -15 zł (z czego -5 zł - Rabat za wyrażenie zgody na otrzymywanie Rachunków/faktur VAT za świadczone + Powyższe „ceny brutto z Rabatami 15zł” + uwzględniają rabat -15 zł (z czego -5 zł - Rabat za wyrażenie zgody na otrzymywanie Rachunków/faktur VAT za świadczone przez Dostawcę Usług usługi telekomunikacyjne drogą elektroniczną na wskazany w umowie adres mail oraz za pośrednictwem EBOK; -10 zł - Rabat pod warunkiem złożenia wniosku o dostarczanie przez Dostawcę Usług treści każdej proponowanej zmiany warunków Umowy, w tym określonych w Umowie, Informacjach Przedumownych oraz danych Dostawcy Usług (chyba że przepisy powszechnie obowiązującego prawa przewidują wyłącznie zawiadomienia poprzez publiczne ogłoszenie), jak również kontaktowanie się ze mną w ramach procedur reklamacyjnych, w tym w szczególności przesłania odpowiedzi na reklamację, na podany w Umowie adres poczty diff --git a/src/content/internet-telewizja/seo.yaml b/src/content/internet-telewizja/seo.yaml index da77018..fb6bba6 100644 --- a/src/content/internet-telewizja/seo.yaml +++ b/src/content/internet-telewizja/seo.yaml @@ -1,30 +1,21 @@ -site: - name: "FUZ Telewizja z Internetem światłowodowym w Wyszkowie" - description: "Stabilny i szybki internet z telewizją" - url: "https://www.fuz.pl" - lang: "pl" - -company: - name: "FUZ Adam Rojek" - phone: "+48 (29) 643 80 55" - email: "biuro@fuz.pl" - street: "ul. Świętojańska 46" - city: "Wyszków" - postal: "07-200" - country: "PL" - lat: 52.597385 - lon: 21.456797 - logo: "/logo.webp" - page: - title: "FUZ Telewizja z Internetem światłowodowym w Wyszkowie" - description: "Szybki, stabilny internet światłowodowy z telewizją w Wyszkowie. Lokalny operator, realny serwis, błyskawiczne wsparcie." + title: "Internet i Telewizja Wyszków - Pakiety Światłowodowe 2w1 | FUZ" + description: "Pakiety Internet + TV w Wyszkowie. Światłowód do 1 Gb/s + ponad 200 kanałów. Jeden rachunek, niższa cena, lokalny serwis. Sprawdź ofertę pakietów 2w1!" image: "/og/telewizja-og.png" url: "/internet-telewizja" keywords: - - internet z telewiazją Wyszków - - internet telewiazja Wyszków + - internet telewizja Wyszków + - internet z telewizją Wyszków + - pakiet internet TV Wyszków - światłowód telewizja Wyszków - - internet światłowodowy telewizja Wyszków - - lokalny operator internetu Wyszków - schema: {} + - internet światłowodowy z TV Wyszków + - pakiet 2w1 internet telewizja + - telewizja przez internet Wyszków + - IPTV Wyszków + - telewizja światłowodowa Wyszków + - internet TV cena Wyszków + - pakiet światłowodowy Wyszków + - internet i telewizja oferta + - kanały telewizyjne Wyszków + - internet telewizja Rząśnik + - internet telewizja Pułtusk \ No newline at end of file diff --git a/src/content/mapa-zasiegu/seo.yaml b/src/content/mapa-zasiegu/seo.yaml new file mode 100644 index 0000000..6d8c031 --- /dev/null +++ b/src/content/mapa-zasiegu/seo.yaml @@ -0,0 +1,23 @@ +page: + title: "Mapa Zasięgu Światłowodu - Sprawdź Dostępność Internetu | FUZ" + description: "Sprawdź czy Twój adres jest w zasięgu sieci światłowodowej FUZ. Interaktywna mapa pokrycia Wyszków i okolic. Weryfikacja dostępności w parę sekund!" + image: "/og/mapa-og.png" + url: "/mapa-zasiegu" + keywords: + - mapa zasięgu światłowodu + - sprawdź dostępność internetu + - zasięg sieci FUZ Wyszków + - pokrycie światłowodu Wyszków + - mapa pokrycia internetu + - sprawdź zasięg pod adresem + - dostępność internetu Wyszków + - gdzie jest światłowód + - weryfikacja adresu internet + - mapa sieci światłowodowej + - zasięg operatora lokalnego + - interaktywna mapa zasięgu + - sprawdź swój adres + - czy mam światłowód + - mapa zasięgu Wyszków + - światłowód Rząśnik + - światłowód Pułtusk diff --git a/src/content/site/global-seo.yaml b/src/content/site/global-seo.yaml new file mode 100644 index 0000000..40475e4 --- /dev/null +++ b/src/content/site/global-seo.yaml @@ -0,0 +1,25 @@ +site: + name: "FUZ Adam Rojek" + description: "Lokalny operator internetu światłowodowego w Wyszkowie i okolicach. Stabilne łącze, szybki serwis, konkurencyjne ceny." + url: "https://www.fuz.pl" + lang: "pl" + +company: + name: "FUZ Adam Rojek" + phone: "+48 29 643 80 55" + email: "biuro@fuz.pl" + street: "ul. Świętojańska 46" + city: "Wyszków" + postal: "07-200" + country: "PL" + lat: 52.597385 + lon: 21.456797 + logo: "/logo.webp" + +schema: + openingHours: "Mo-Fr 09:00-17:00" + priceRange: "$" + areaServed: + - Wyszków + - Rząśnik + - Pułtusk \ No newline at end of file diff --git a/src/content/telefon/seo.yaml b/src/content/telefon/seo.yaml index c8efb56..abff98c 100644 --- a/src/content/telefon/seo.yaml +++ b/src/content/telefon/seo.yaml @@ -1,33 +1,21 @@ -site: - name: "FUZ Telefon i Internet światłowodowy w Wyszkowie" - description: "Usługa telefonu wraz z stabilnym i szybkim internet" - url: "https://www.fuz.pl" - lang: "pl" - -company: - name: "FUZ Adam Rojek" - phone: "+48 (29) 643 80 55" - email: "biuro@fuz.pl" - street: "ul. Świętojańska 46" - city: "Wyszków" - postal: "07-200" - country: "PL" - lat: 52.597385 - lon: 21.456797 - logo: "/logo.webp" - page: - title: "FUZ Telefon i Internet światłowodowy w Wyszkowie" - description: "Szybki, stabilny internet światłowodowy w Wyszkowie z usługa telefonu. Lokalny operator, realny serwis, błyskawiczne wsparcie." + title: "Telefon Stacjonarny i Internet Wyszków | FUZ" + description: "Telefon stacjonarny + Internet światłowodowy w Wyszkowie. Niskie ceny międzynarodowych, jeden rachunek. Sprawdź ofertę telefonu!" image: "/og/telefon-og.png" url: "/telefon" keywords: - - telefon - - telefon Wyszków + - telefon stacjonarny Wyszków - telefon internet Wyszków - - internet Wyszków - - światłowód Wyszków - - internet światłowodowy Wyszków - - lokalny operator internetu Wyszków - - schema: {} + - VoIP Wyszków + - telefonia stacjonarna Wyszków + - telefon światłowodowy Wyszków + - pakiet telefon internet + - tani telefon stacjonarny + - telefon przez internet + - telefonia VoIP Wyszków + - telefon światłowód Wyszków + - połączenia międzynarodowe tanie + - telefon domowy Wyszków + - telefon stacjonarny oferta + - internet telefon Rząśnik + - internet telefon Pułtusk \ No newline at end of file diff --git a/src/islands/jambox/JamboxChannelsSearch.jsx b/src/islands/jambox/JamboxChannelsSearch.jsx index 0724b09..30c407a 100644 --- a/src/islands/jambox/JamboxChannelsSearch.jsx +++ b/src/islands/jambox/JamboxChannelsSearch.jsx @@ -141,7 +141,7 @@ export default function JamboxChannelsSearch() { return (
-

Wyszukiwanie kanałów w pakietach telewizji

+

Wyszukiwanie kanałów w pakietach telewizji

{/* SEKCJA "CHCIAŁBYM MIEĆ TE KANAŁY" */}
diff --git a/src/islands/phone/PhoneCards.jsx b/src/islands/phone/PhoneCards.jsx index 13f375e..6e4e87a 100644 --- a/src/islands/phone/PhoneCards.jsx +++ b/src/islands/phone/PhoneCards.jsx @@ -64,6 +64,7 @@ function PhoneOfferCard({ card }) { cenaOpis={priceLabel} features={features} actions={[]} // Brak akcji - karty telefoniczne są tylko informacyjne + withStart={false} /> ); } diff --git a/src/layouts/BaseHead.astro b/src/layouts/BaseHead.astro index 95a4e8d..e6dfe19 100644 --- a/src/layouts/BaseHead.astro +++ b/src/layouts/BaseHead.astro @@ -1,130 +1,76 @@ --- -import yaml from "js-yaml"; -import fs from "fs"; +import { + loadGlobalSeo, + buildSeoMeta, + mergeFaviconConfig, + type SeoConfig, + type FaviconConfig +} from "../lib/astro-helpers"; -const seo = Astro.props.seo ?? {}; -const globalSeo = yaml.load( - fs.readFileSync("./src/content/home/seo.yaml", "utf8"), -); +const globalSeo = loadGlobalSeo(); // ← Globalny +const pageSeo = Astro.props.seo; // ← Ze strony -const { site, company } = globalSeo; -const page = seo.page ?? {}; +const origin = Astro.url?.origin || globalSeo.site.url; +const meta = buildSeoMeta(origin, globalSeo, pageSeo as SeoConfig); -// ===== helpers ===== -function stripTrailingSlash(s = "") { - return String(s).replace(/\/$/, ""); -} -function stripLeadingSlash(s = "") { - return String(s).replace(/^\//, ""); -} -function isAbsoluteUrl(s = "") { - return /^https?:\/\//i.test(String(s)); -} -function joinUrl(base = "", path = "") { - const b = stripTrailingSlash(base); - const p = String(path || ""); - if (!p) return b; - if (isAbsoluteUrl(p)) return p; - return `${b}/${stripLeadingSlash(p)}`; -} +// Favicon configuration - można przekazać custom przez props +const faviconConfig = mergeFaviconConfig(Astro.props.favicon as Partial); -// ===== origin / base for meta ===== -// Astro.url.origin daje aktualny host (test/prod) – dokładnie to chcemy do OG/WhatsApp -const origin = Astro.url?.origin || site.url; -const baseUrl = stripTrailingSlash(origin); - -// ===== page fields ===== -const title = page.title ?? site.name; -const description = page.description ?? site.description; - -const rawImage = page.image ?? site.logo; -const image = joinUrl(baseUrl, rawImage); - -const canonical = joinUrl(baseUrl, page.url ?? "/"); -const keywords = page.keywords ?? []; - -const extraSchema = page.schema ?? null; - -// JSON-LD objects (tu też używamy baseUrl, żeby nie rozjeżdżało się między test/prod) -const schemaWebsite = { - "@context": "https://schema.org", - "@type": "WebSite", - url: baseUrl, - name: site.name, - potentialAction: { - "@type": "SearchAction", - target: `${baseUrl}/wyszukiwarka?query={search_term_string}`, - "query-input": "required name=search_term_string", - }, -}; - -const schemaLocalBusiness = { - "@context": "https://schema.org", - "@type": "LocalBusiness", - name: company.name, - image: joinUrl(baseUrl, company.logo), - telephone: company.phone, - email: company.email, - address: { - "@type": "PostalAddress", - streetAddress: company.street, - addressLocality: company.city, - postalCode: company.postal, - addressCountry: company.country, - }, - geo: { - "@type": "GeoCoordinates", - latitude: company.lat, - longitude: company.lon, - }, - url: baseUrl, -}; - -// JSON strings -const jsonWebsite = JSON.stringify(schemaWebsite); -const jsonBusiness = JSON.stringify(schemaLocalBusiness); -const jsonExtra = extraSchema ? JSON.stringify(extraSchema) : null; +const jsonWebsite = JSON.stringify(meta.schemaWebsite); +const jsonBusiness = JSON.stringify(meta.schemaLocalBusiness); +const jsonExtra = meta.extraSchema ? JSON.stringify(meta.extraSchema) : null; --- - {title} - + {meta.title} + { - keywords.length > 0 && ( - + meta.keywords.length > 0 && ( + ) } + + + + + + + + + + - + + - - - - + + + + - - + + - - - + + + - + \ No newline at end of file diff --git a/src/pages/mapa-zasiegu/index.astro b/src/pages/mapa-zasiegu/index.astro index 78068d5..0152fd3 100644 --- a/src/pages/mapa-zasiegu/index.astro +++ b/src/pages/mapa-zasiegu/index.astro @@ -2,13 +2,14 @@ import DefaultLayout from "../../layouts/DefaultLayout.astro"; import MapGoogle from "../../components/maps/MapGoogle.astro"; import RangeForm from "../../islands/RangeForm.jsx"; - +import { loadYaml, safeArray } from "../../lib/astro-helpers"; import "../../styles/map-google.css"; const apiKey = import.meta.env.PUBLIC_GOOGLE_MAPS_KEY; const lat = 52.597388; const lon = 21.456797; const mapStyleId = "8e0a97af9476f2d3"; +const seo = loadYaml("./src/content/mapa-zasiegu/seo.yaml"); --- - +
- -
{ const map = window.getActiveMap(); if (map && window.google?.maps) { @@ -88,7 +86,6 @@ const mapStyleId = "8e0a97af9476f2d3"; const map = window.getActiveMap(); if (!map) return; - // Czekamy aż API będzie gotowe if (!window.google?.maps?.importLibrary) { await new Promise((resolve) => { const int = setInterval(() => { @@ -140,7 +137,6 @@ const mapStyleId = "8e0a97af9476f2d3"; window._activeMarker = marker; - // InfoWindow const html = `
@@ -167,4 +163,4 @@ const mapStyleId = "8e0a97af9476f2d3"; info.open({ map, anchor: marker }); }; - + \ No newline at end of file diff --git a/src/pages/premium/[tid].astro b/src/pages/premium/[tid].astro index 5c0dd57..5d2adca 100644 --- a/src/pages/premium/[tid].astro +++ b/src/pages/premium/[tid].astro @@ -1,9 +1,8 @@ --- import DefaultLayout from "../../layouts/DefaultLayout.astro"; -import yaml from "js-yaml"; -import fs from "node:fs"; import Markdown from "../../islands/Markdown.jsx"; import AddonChannelsGrid from "../../islands/jambox/AddonChannelsModal.jsx"; +import { loadYaml, safeArray } from "../../lib/astro-helpers"; import "../../styles/jambox-tematyczne.css"; type AddonPriceRow = { @@ -43,11 +42,9 @@ type TvAddonsDoc = { grupy?: Record; }; -const doc = yaml.load( - fs.readFileSync("./src/content/internet-telewizja/tv-addons.yaml", "utf8"), -) as TvAddonsDoc; +const doc = loadYaml("./src/content/internet-telewizja/tv-addons.yaml"); -const addons = Array.isArray(doc?.dodatki) ? doc.dodatki : []; +const addons = safeArray(doc?.dodatki); const groupMeta = doc?.grupy ?? {}; const tid = Number(Astro.params.tid); @@ -63,8 +60,7 @@ const viewAddons = pickedGroup ? addons.filter((a) => String(a?.group ?? "").trim() === pickedGroup) : [picked]; -const footerCta = - pickedGroup ? groupMeta[pickedGroup]?.rejestracja : undefined; +const footerCta = pickedGroup ? groupMeta[pickedGroup]?.rejestracja : undefined; --- - {/* MEDIA — odpowiednik */}
{pkgName ? ( - {/* TEKST */}
{pkgName &&

{pkgName}

} {addon?.opis && } @@ -129,4 +123,4 @@ const footerCta =
) : null} -
+
\ No newline at end of file diff --git a/src/pages/premium/index.astro b/src/pages/premium/index.astro index 1cc162c..2eff480 100644 --- a/src/pages/premium/index.astro +++ b/src/pages/premium/index.astro @@ -1,9 +1,8 @@ --- import DefaultLayout from "../../layouts/DefaultLayout.astro"; -import yaml from "js-yaml"; -import fs from "node:fs"; import Markdown from "../../islands/Markdown.jsx"; import AddonChannelsGrid from "../../islands/jambox/AddonChannelsModal.jsx"; +import { loadYaml, safeArray } from "../../lib/astro-helpers"; import "../../styles/jambox-tematyczne.css"; type AddonPriceRow = { @@ -24,7 +23,6 @@ type TvAddon = { group_mode?: string; }; -// ✅ OPCJA A: metadane grupy + CTA type GroupCta = { label?: string; href?: string; @@ -42,20 +40,16 @@ type TvAddonsDoc = { opis?: string; cena_opis?: string; dodatki?: TvAddon[]; - grupy?: Record; // ✅ + grupy?: Record; }; -const doc = yaml.load( - fs.readFileSync("./src/content/internet-telewizja/tv-addons.yaml", "utf8"), -) as TvAddonsDoc; +const doc = loadYaml("./src/content/internet-telewizja/tv-addons.yaml"); const pageTitle = doc?.tytul ?? "Dodatkowe pakiety TV"; const pageDesc = doc?.opis ?? ""; -const addons: TvAddon[] = Array.isArray(doc?.dodatki) ? doc.dodatki : []; +const addons = safeArray(doc?.dodatki); const detailsBase = "/pakiety-premium"; - -// ✅ mapa meta grup (np. hbo_max -> { rejestracja: {...} }) const groupMeta: Record = doc?.grupy ?? {}; type Group = { @@ -64,6 +58,7 @@ type Group = { items: TvAddon[]; groupId?: string; }; + const groupsMap = new Map(); for (const a of addons) { @@ -95,7 +90,7 @@ const groups: Group[] = Array.from(groupsMap.values()); { groups.map((group, groupIndex) => { const isSingle = group.key.startsWith("s:"); - const gId = String(group.groupId ?? "").trim(); // np. "hbo_max" + const gId = String(group.groupId ?? "").trim(); const meta = gId ? groupMeta[gId] : undefined; const footerCta = meta?.rejestracja; @@ -111,7 +106,6 @@ const groups: Group[] = Array.from(groupsMap.values()); const pkgName = String(addon?.nazwa ?? "").trim(); const hasYamlImage = !!String(addon?.image ?? "").trim(); - // ✅ zachowanie jak wcześniej (1 kolumna + ukrycie media gdy brak) const assumeHasMedia = pkgName ? true : hasYamlImage; const href = @@ -148,7 +142,6 @@ const groups: Group[] = Array.from(groupsMap.values()); ); })} - {/* ✅ STOPKA GRUPY: przycisk rejestracji dla całej grupy */} {!isSingle && footerCta?.href && footerCta?.label ? (