Programmatic SEO w Astro: Jak zbudowaliśmy ponad 100 stron lokalnych z wynikiem Core Web Vitals 98+ bez CMS

Budowa katalogu branżowego, agregatora usług lokalnych lub portalu na wiele rynków zazwyczaj wpędza zespoły programistyczne w tę samą pułapkę: ciężkie instalacje WordPressa z 40 wtyczkami albo konfiguracje Headless CMS (Strapi, Sanity), które generują setki euro miesięcznych kosztów API i powolny czas TTFB na poziomie 800ms.

Kiedy projektowaliśmy architekturę LocalAnyDay, platformy usług remontowych i utrzymania nieruchomości działającej w Wielkiej Brytanii i Polsce, całkowicie zrezygnowaliśmy z tradycyjnych CMS-ów.

Zamiast tego postawiliśmy całą platformę na Astro, wykorzystując statyczne kolekcje treści, warstwę danych JSON kompilowaną w czasie budowy i lekkie wyspy interaktywne w czystym Vanilla JavaScript. Rezultat: ponad 100 lokalnych stron miast z wynikiem PageSpeed 98+ na urządzeniach mobilnych, czasem TTFB poniżej 150ms i zerowymi opłatami abonamentowymi za CMS.

Podsumowanie wykonawcze


1. Wąskie gardło Headless CMS w Programmatic SEO

Większość wdrożeń Programmatic SEO przegrywa jeszcze przed zaindeksowaniem. Gdy roboty wyszukiwarki, takie jak Googlebot, trafiają na nową domenę z ponad 100 adresami URL, przydzielają jej minimalny Crawl Budget.

Jeśli Twoje strony polegają na dynamicznych zapytaniach do bazy danych (zapytania PHP w WordPressie lub SSR w Next.js pobierający dane ze zdalnego CMS):

  1. TTFB przekracza 600 - 1200ms: Roboty indeksujące napotykają barierę opóźnień i rezygnują z głębszego przeszukiwania klastrów miast.
  2. Przesunięcia układu niszczą Core Web Vitals: Kaskadowe nawadnianie (hydration) po stronie klienta powoduje przesunięcia elementów (CLS), spychając wyniki mobilne w czerwoną strefę (<60).
  3. Limity zapytań API blokują proces budowy: Przebudowa serwisu liczącego setki podstron przez API zdalnego CMS regularnie uderza w limity lub wymaga płatnych planów enterprise.

Dzięki przeniesieniu całego procesu generowania stron do czasu kompilacji w Astro, każda podstrona powstaje jako czysty, statyczny plik HTML i CSS. Przy wejściu użytkownika nie ma ani jednego zapytania do bazy danych.

PORÓWNANIE ARCHITEKTURY: CMS VS AI-NATIVE ASTRO
Runtime Benchmark
🤖 Robot / Użytkownik Zapytanie HTTP
PHP / Baza Danych Dynamiczne SQL
🐢 840ms TTFB Utrata Crawl Budget
🤖 Robot / Użytkownik Zapytanie HTTP
Edge Cache Gotowy HTML/CSS
🚀 65ms TTFB Natychmiastowe 99/100

2. Architektura katalogów i kolekcje w czasie kompilacji

W naszej architekturze każde miasto, kategoria usług i stawki rynkowe są zapisane jako ustrukturyzowane pliki JSON i Markdown bezpośrednio w repozytorium:

/src/content/
├── services/
│   ├── driveway-cleaning.json
│   └── floor-sanding.json
└── locations/
    ├── uk/
    │   ├── bristol.json
    │   └── bath.json
    └── pl/
        └── wroclaw.json

Funkcja getStaticPaths() w Astro przetwarza te zbiory danych, generując kanoniczne klastry stron z precyzyjnie powiązanymi linkami wewnętrznymi:

// src/pages/[country]/[city]/[service].astro
import { getCollection } from 'astro:content';

export async function getStaticPaths() {
  const cities = await getCollection('cities');
  const services = await getCollection('services');

  return cities.flatMap((city) => {
    return services.map((service) => ({
      params: {
        country: city.data.countryCode,
        city: city.slug,
        service: service.slug,
      },
      props: { city, service },
    }));
  });
}

const { city, service } = Astro.props;

Podczas budowy Astro przetwarza całe drzewo danych i generuje komplet zoptymalizowanych plików HTML w czasie poniżej 40 sekund.


3. Interaktywne narzędzia wycen bez narzutu frameworków

Strona wygenerowana automatycznie, która zawiera wyłącznie statyczny tekst, jest traktowana przez algorytmy wyszukiwarek jako treść o niskiej wartości (thin content). Aby zapewnić realną wartość dla odwiedzających, nasze lokalne podstrony zawierają interaktywne kalkulatory stawek, suwaki powierzchni oraz porównywarki zdjęć przed i po wykonaniu prac.

Zamiast ładować ciężkie biblioteki React czy Vue (dodające 45 - 80 KB do wagi strony), stworzyliśmy te komponenty jako natywne Web Components w czystym JavaScript:

// Lekki kalkulator kosztów (0 KB zewnętrznych zależności)
class ServicePriceCalculator extends HTMLElement {
  connectedCallback() {
    const slider = this.querySelector('input[type="range"]');
    const output = this.querySelector('.calculated-price');
    const baseRate = parseFloat(this.dataset.baseRate || '45');

    slider.addEventListener('input', (e) => {
      const area = parseFloat(e.target.value);
      const total = Math.round(area * baseRate);
      output.textContent = `${total} PLN`;
    });
  }
}
customElements.define('service-price-calculator', ServicePriceCalculator);

Ponieważ Astro domyślnie nie wysyła żadnego kodu JavaScript na klienta, skrypt kalkulatora uruchamia się wyłącznie tam, gdzie został wprost zaimportowany. Łączny rozmiar skryptów przesyłanych na smartfon użytkownika to zaledwie 3.2 KB.


4. Zestawienie wydajności w praktyce

Przetestowaliśmy statyczne wdrożenie na Astro w zestawieniu ze standardowym WordPressem oraz dynamicznym serwerem Next.js na identycznych maszynach Hetzner VPS:

MetrykaTradycyjny WordPressNext.js 16 (SSR + CMS)Architektura Astro ILF Studio
Mobilna wydajność (CWV)48 / 10078 / 10099 / 100
Time to First Byte (TTFB)840ms380ms72ms
Largest Contentful Paint (LCP)3.6s2.1s0.9s
Cumulative Layout Shift (CLS)0.180.040.00
Paczka JS na telefonie240 KB85 KB3.2 KB
Koszty serwera i API60 € / mies.120 € / mies.5 € / mies. (Standardowy VPS)

5. Jak uniknąć filtrów Scaled Content Abuse

Aktualizacje algorytmów Google skutecznie eliminują generowany masowo spam, w którym szablon zmienia jedynie nazwę miejscowości.

Aby zapewnić pełne bezpieczeństwo i stabilne pozycje w rankingu organicznym, nasz proces podlega 3 zasadom inżynieryjnym:

  1. Unikalne lokalne dane: Plik konfiguracyjny każdego miasta zawiera faktyczne lokalne normy utylizacji, twardość wody, lokalne regulacje odprowadzania ścieków i realne widełki cenowe.
  2. Kroplowe tempo publikacji: Wprowadzamy podstrony partiami (15 - 20 kluczowych stron na start, a następnie kolejne miasto co 7 - 10 dni), co symuluje naturalny rozrost serwisu dla robotów indeksujących.
  3. Precyzyjne mikrodane Schema.org: Każda strona generuje kompletne grafy Service, LocalBusiness i BreadcrumbList powiązane z regionalnymi identyfikatorami.

Kluczowe wnioski dla przedsiębiorców i zespołów IT