Seo poprawki
This commit is contained in:
@@ -12,6 +12,7 @@
|
|||||||
"@astrojs/preact": "^4.1.3",
|
"@astrojs/preact": "^4.1.3",
|
||||||
"@preact/signals": "^2.5.1",
|
"@preact/signals": "^2.5.1",
|
||||||
"astro": "^5.16.0",
|
"astro": "^5.16.0",
|
||||||
|
"globby": "^16.0.0",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
"marked": "^17.0.1",
|
"marked": "^17.0.1",
|
||||||
"preact": "^10.27.2"
|
"preact": "^10.27.2"
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ ctas:
|
|||||||
href: "/internet-telewizja"
|
href: "/internet-telewizja"
|
||||||
primary: false
|
primary: false
|
||||||
- label: "Zobacz ofertę Internetu Radiowego"
|
- label: "Zobacz ofertę Internetu Radiowego"
|
||||||
href: "/internet-radio"
|
href: "/internet-radiowy"
|
||||||
primary: false
|
primary: false
|
||||||
# - label: "Sprawdź dostępność"
|
# - label: "Sprawdź dostępność"
|
||||||
# href: "/mapa-zasiegu"
|
# href: "/mapa-zasiegu"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
site:
|
site:
|
||||||
name: "FUZ – Internet światłowodowy i radiowy w Wyszkowie"
|
name: "FUZ – Internet światłowodowy i radiowy w Wyszkowie"
|
||||||
description: "Stabilny i szybki internet"
|
description: "Stabilny i szybki internet w Wyszkowie i okolicach"
|
||||||
url: "https://www.fuz.pl"
|
url: "https://www.fuz.pl"
|
||||||
lang: "pl"
|
lang: "pl"
|
||||||
|
|
||||||
@@ -15,3 +15,15 @@ company:
|
|||||||
lat: 52.597385
|
lat: 52.597385
|
||||||
lon: 21.456797
|
lon: 21.456797
|
||||||
logo: "/images/logo-fuz.webp"
|
logo: "/images/logo-fuz.webp"
|
||||||
|
|
||||||
|
page:
|
||||||
|
title: "FUZ – Internet światłowodowy i radiowy w Wyszkowie"
|
||||||
|
description: "Szybki, stabilny internet światłowodowy i radiowy w Wyszkowie. Lokalny operator, realny serwis, błyskawiczne wsparcie."
|
||||||
|
image: "/images/og-home.webp"
|
||||||
|
url: "/"
|
||||||
|
keywords:
|
||||||
|
- internet Wyszków
|
||||||
|
- światłowód Wyszków
|
||||||
|
- internet radiowy Wyszków
|
||||||
|
- lokalny operator internetu
|
||||||
|
schema: {}
|
||||||
|
|||||||
@@ -2,41 +2,43 @@
|
|||||||
import yaml from "js-yaml";
|
import yaml from "js-yaml";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
|
|
||||||
const { seo } = Astro.props;
|
// SEO z YAML (np. import seo from "../content/seo/home.yaml")
|
||||||
|
const seo = Astro.props.seo ?? {};
|
||||||
|
|
||||||
// Load global SEO config
|
// Global SEO (site + company)
|
||||||
const globalSeo = yaml.load(
|
const globalSeo = yaml.load(
|
||||||
fs.readFileSync("./src/content/seo/home.yaml", "utf8")
|
fs.readFileSync("./src/content/seo/home.yaml", "utf8")
|
||||||
);
|
);
|
||||||
|
|
||||||
const { site, company } = globalSeo;
|
const { site, company } = globalSeo;
|
||||||
|
|
||||||
const {
|
// Page SEO (sekcja "page" w YAML)
|
||||||
title = site.name,
|
const page = seo.page ?? {};
|
||||||
description = site.description,
|
|
||||||
url = "/",
|
|
||||||
image = site.logo,
|
|
||||||
keywords = [],
|
|
||||||
schema = {}
|
|
||||||
} = seo ?? {};
|
|
||||||
|
|
||||||
const canonical = site.url + url;
|
// FINAL VALUES
|
||||||
|
const title = page.title ?? site.name;
|
||||||
|
const description = page.description ?? site.description;
|
||||||
|
const image = page.image ?? site.logo;
|
||||||
|
const canonical = site.url + (page.url ?? "/");
|
||||||
|
const keywords = page.keywords ?? [];
|
||||||
|
|
||||||
/* PREPARE JSON-LD AS SAFE STRINGS */
|
// Extra structured data (optional)
|
||||||
|
const extraSchema = page.schema ?? null;
|
||||||
|
|
||||||
const schemaWebsite = JSON.stringify({
|
// JSON-LD objects
|
||||||
|
const schemaWebsite = {
|
||||||
"@context": "https://schema.org",
|
"@context": "https://schema.org",
|
||||||
"@type": "WebSite",
|
"@type": "WebSite",
|
||||||
"url": site.url,
|
"url": site.url,
|
||||||
"name": site.name,
|
"name": site.name,
|
||||||
"potentialAction": {
|
"potentialAction": {
|
||||||
"@type": "SearchAction",
|
"@type": "SearchAction",
|
||||||
"target": site.url + "/wyszukiwarka?query={search_term_string}",
|
"target": `${site.url}/wyszukiwarka?query={search_term_string}`,
|
||||||
"query-input": "required name=search_term_string"
|
"query-input": "required name=search_term_string"
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
const schemaLocalBusiness = JSON.stringify({
|
const schemaLocalBusiness = {
|
||||||
"@context": "https://schema.org",
|
"@context": "https://schema.org",
|
||||||
"@type": "LocalBusiness",
|
"@type": "LocalBusiness",
|
||||||
"name": company.name,
|
"name": company.name,
|
||||||
@@ -56,13 +58,14 @@ const schemaLocalBusiness = JSON.stringify({
|
|||||||
"longitude": company.lon
|
"longitude": company.lon
|
||||||
},
|
},
|
||||||
"url": site.url
|
"url": site.url
|
||||||
});
|
};
|
||||||
|
|
||||||
/* Extra schema if passed from page */
|
// JSON strings
|
||||||
const schemaExtra = Object.keys(schema).length > 0
|
const jsonWebsite = JSON.stringify(schemaWebsite);
|
||||||
? JSON.stringify(schema)
|
const jsonBusiness = JSON.stringify(schemaLocalBusiness);
|
||||||
: null;
|
const jsonExtra = extraSchema ? JSON.stringify(extraSchema) : null;
|
||||||
---
|
---
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
@@ -76,7 +79,7 @@ const schemaExtra = Object.keys(schema).length > 0
|
|||||||
|
|
||||||
<link rel="canonical" href={canonical} />
|
<link rel="canonical" href={canonical} />
|
||||||
|
|
||||||
<!-- OG -->
|
<!-- OpenGraph -->
|
||||||
<meta property="og:type" content="website" />
|
<meta property="og:type" content="website" />
|
||||||
<meta property="og:title" content={title} />
|
<meta property="og:title" content={title} />
|
||||||
<meta property="og:description" content={description} />
|
<meta property="og:description" content={description} />
|
||||||
@@ -90,15 +93,15 @@ const schemaExtra = Object.keys(schema).length > 0
|
|||||||
<meta name="twitter:description" content={description} />
|
<meta name="twitter:description" content={description} />
|
||||||
<meta name="twitter:image" content={image} />
|
<meta name="twitter:image" content={image} />
|
||||||
|
|
||||||
<!-- JSON-LD (Website) -->
|
<!-- JSON-LD: Website -->
|
||||||
<script type="application/ld+json">{schemaWebsite}</script>
|
<script type="application/ld+json" set:html={jsonWebsite}></script>
|
||||||
|
|
||||||
<!-- JSON-LD (LocalBusiness) -->
|
<!-- JSON-LD: LocalBusiness -->
|
||||||
<script type="application/ld+json">{schemaLocalBusiness}</script>
|
<script type="application/ld+json" set:html={jsonBusiness}></script>
|
||||||
|
|
||||||
<!-- Optional per-page schema -->
|
<!-- JSON-LD: Extra schema -->
|
||||||
{schemaExtra && (
|
{jsonExtra && (
|
||||||
<script type="application/ld+json">{schemaExtra}</script>
|
<script type="application/ld+json" set:html={jsonExtra}></script>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<slot />
|
<slot />
|
||||||
|
|||||||
@@ -9,7 +9,9 @@ const { seo } = Astro.props;
|
|||||||
---
|
---
|
||||||
|
|
||||||
<html lang="pl" class="scroll-smooth">
|
<html lang="pl" class="scroll-smooth">
|
||||||
<BaseHead seo={seo} />
|
<head>
|
||||||
|
<BaseHead seo={seo} />
|
||||||
|
</head>
|
||||||
|
|
||||||
<body class="min-h-screen flex flex-col">
|
<body class="min-h-screen flex flex-col">
|
||||||
<Header />
|
<Header />
|
||||||
|
|||||||
50
src/pages/sitemap.xml.js
Normal file
50
src/pages/sitemap.xml.js
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import { globby } from 'globby';
|
||||||
|
|
||||||
|
export async function GET() {
|
||||||
|
const base = "https://www.fuz.pl";
|
||||||
|
|
||||||
|
// Pobieramy wszystkie pliki .astro
|
||||||
|
const files = await globby([
|
||||||
|
"src/pages/**/*.astro",
|
||||||
|
"!src/pages/_*.astro", // pomiń pliki zaczynające się od _
|
||||||
|
"!src/pages/**/[...*", // pomiń catch-all
|
||||||
|
"!src/pages/**/[**", // pomiń dynamiczne parametry
|
||||||
|
"!src/pages/sitemap.xml.js", // pomiń samą sitemapę
|
||||||
|
"!src/pages/api/**" // pomiń API endpoints
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Konwersja ścieżek plikowych → URL-e
|
||||||
|
const urls = files.map((file) => {
|
||||||
|
let url = file
|
||||||
|
.replace("src/pages", "")
|
||||||
|
.replace(".astro", "");
|
||||||
|
|
||||||
|
// obsługa index: /index.astro → /
|
||||||
|
if (url.endsWith("/index")) {
|
||||||
|
url = url.replace("/index", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
return url;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Budowa XML
|
||||||
|
const body = `<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||||
|
${urls
|
||||||
|
.map((url) => {
|
||||||
|
return `
|
||||||
|
<url>
|
||||||
|
<loc>${base}${url}</loc>
|
||||||
|
<changefreq>weekly</changefreq>
|
||||||
|
<priority>${url === "/" ? "1.0" : "0.8"}</priority>
|
||||||
|
</url>`;
|
||||||
|
})
|
||||||
|
.join("")}
|
||||||
|
</urlset>`;
|
||||||
|
|
||||||
|
return new Response(body, {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/xml",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user