feat: complete website implementation

This commit is contained in:
Radosław Smoliński
2026-06-21 21:53:15 +02:00
parent b147112bdc
commit dfd3888517
110 changed files with 18276 additions and 217 deletions
+99
View File
@@ -0,0 +1,99 @@
# 01 — Architektura
Definiuje strukturę projektu, routing i wzorce. Trzymaj się jej ściśle.
---
## Struktura katalogów
```
.
├── AGENTS.md
├── app/
│ ├── layout.tsx # root layout: font, header, footer, metadata bazowe
│ ├── page.tsx # strona główna
│ ├── globals.css # Tailwind + CSS variables (tokeny)
│ ├── klimatyzacja/
│ │ └── page.tsx
│ ├── pompy-ciepla/
│ │ └── page.tsx
│ ├── uslugi-domowe/
│ │ ├── page.tsx # rozdzielnik
│ │ ├── remonty/page.tsx
│ │ ├── hydraulika/page.tsx
│ │ └── serwis-agd/page.tsx
│ ├── realizacje/
│ │ └── page.tsx
│ ├── blog/
│ │ ├── page.tsx
│ │ └── [slug]/page.tsx
│ ├── o-nas/page.tsx
│ ├── kontakt/
│ │ ├── page.tsx
│ │ └── actions.ts # Server Action formularza
│ ├── sklep/
│ │ ├── page.tsx # listing + filtry
│ │ └── [slug]/page.tsx # karta produktu
│ ├── koszyk/page.tsx
│ ├── raty/page.tsx
│ ├── (formalne)/ # route group dla stron formalnych
│ │ ├── regulamin/page.tsx
│ │ ├── polityka-prywatnosci/page.tsx
│ │ ├── reklamacje/page.tsx
│ │ ├── dostawa/page.tsx
│ │ └── gwarancja/page.tsx
│ ├── sitemap.ts
│ ├── robots.ts
│ ├── not-found.tsx
│ └── loading.tsx
├── components/
│ ├── ui/ # shadcn/ui (button, card, accordion, input, ...)
│ ├── layout/ # Header, Footer, MobileMenu, TrustBar, NavDropdown
│ ├── sections/ # sekcje stron: Hero, ServicesGrid, ProcessSteps, FAQ, ...
│ ├── shop/ # ProductCard, ProductFilters, CartSummary, ...
│ └── common/ # SectionHeading, CTAButton, StatCounter, Placeholder, ...
├── content/ # dane (mock): products.ts, projects.ts, posts.ts, faq.ts, ...
├── lib/ # utils.ts, constants.ts, cart-store.ts (zustand), validations.ts (zod)
├── types/ # product.ts, project.ts, post.ts, ...
├── public/ # zdjęcia placeholder, logo, ikony, og-images
├── tailwind.config.ts
└── tsconfig.json # alias @/*
```
---
## Zasady routingu
- App Router, Server Components domyślnie.
- Strony formalne w route group `(formalne)` — wspólny, prosty layout tekstowy.
- Dynamiczne trasy: `blog/[slug]`, `sklep/[slug]` — `generateStaticParams` z danych w `content/`.
- Każda strona eksportuje `metadata` (lub `generateMetadata` dla dynamicznych).
---
## Wzorce komponentów
1. **Strona = kompozycja sekcji.** `page.tsx` importuje komponenty z `components/sections/`
i przekazuje im dane. Strona nie zawiera logiki layoutu sekcji.
2. **Sekcja = jeden komponent.** Np. `HeroSection`, `ServicesGrid`, `ProcessSteps`, `FaqAccordion`,
`PricingTable`, `Testimonials`, `StatsBar`, `BlogPreview`, `CtaBanner`.
3. **Współdzielone bloki** (Hero, FAQ, CTA) przyjmują propsy, by można było ich użyć na wielu stronach
z różną treścią — nie duplikuj.
4. **Dane oddzielone od prezentacji** — komponent dostaje dane przez propsy, źródło to `content/`.
5. **Client Components** tylko: formularze, koszyk (Zustand), dropdowny nawigacji, mobile menu,
slidery galerii, kalkulator rat, filtry sklepu.
---
## Stan aplikacji
- Koszyk: Zustand store w `lib/cart-store.ts` (dodaj/usuń/zmień ilość/suma). Persist do localStorage.
- Reszta: stan lokalny komponentów. Bez globalnego store poza koszykiem.
---
## Obsługa obrazów
- Wszystkie zdjęcia jako placeholdery na tym etapie (komponent `Placeholder` lub pliki w `public/`).
- W kodzie oznacz komentarzem `{/* TODO: docelowe zdjęcie — opis */}`, gdzie wstawić realne foto.
- Zawsze `next/image` z `alt`, `width/height` lub `fill` + `sizes`.
+88
View File
@@ -0,0 +1,88 @@
# 02 — Design System
Pełna definicja systemu projektowego. Zaimplementuj jako tokeny w `tailwind.config.ts`
i CSS variables w `globals.css`. Wszystkie komponenty korzystają z tokenów, nie z wartości „na sztywno".
---
## Paleta kolorów
| Token | Hex | Zastosowanie |
|-------|-----|--------------|
| `primary` (granat) | `#0F2A47` | nagłówki, header, footer, tekst akcentowany |
| `primary-light` | `#1B3D63` | hover na elementach primary |
| `accent` (cyjan) | `#2BA8E0` | akcenty „chłodu", linki, ikony, podkreślenia |
| `accent-light` | `#E3F4FC` | tła sekcji związanych z klimatyzacją |
| `cta` (pomarańcz) | `#F39320` | przyciski akcji, wyróżnienia konwersji |
| `cta-hover` | `#D97D0D` | hover przycisków CTA |
| `bg` | `#FFFFFF` | główne tło |
| `bg-muted` | `#F5F7FA` | tła naprzemiennych sekcji |
| `text` | `#1A2230` | tekst podstawowy |
| `text-muted` | `#5A6678` | tekst drugorzędny, opisy |
| `border` | `#E2E8F0` | obramowania kart, separatory |
| `success` | `#16A34A` | potwierdzenia, „dostępne" |
Tryb: na start jasny. Przygotuj zmienne tak, by dark mode dało się dodać później bez przepisywania.
---
## Typografia
- Font: **Inter** lub **Poppins** przez `next/font/google` (subset latin + latin-ext dla polskich znaków).
- Skala (desktop / mobile):
- H1: 48–56px / 32–36px, bold, line-height 1.1
- H2: 36–40px / 28px, bold
- H3: 24–28px / 20px, semibold
- Body: 16–18px / 16px, regular, line-height 1.6
- Small: 14px
- Nagłówki w kolorze `primary`. Tekst w `text`. Opisy w `text-muted`.
- Maksymalna szerokość bloku tekstu: ~70 znaków (czytelność).
---
## Spacing i layout
- Kontener: max-width 1280px, padding boczny 16px (mobile) / 24–32px (desktop), wyśrodkowany.
- Odstępy między sekcjami: 80–120px desktop / 48–64px mobile. Dużo powietrza.
- Siatka kart: grid responsywny (1 kol. mobile → 2 → 3/4 desktop), gap 24px.
- Sekcje naprzemiennie `bg` i `bg-muted` dla rytmu wizualnego.
---
## Komponenty UI (na bazie shadcn/ui, dostosowane do tokenów)
- **Button** — warianty: `cta` (pomarańcz, główny), `primary` (granat), `outline`, `ghost`.
Zaokrąglenie `rounded-lg`, padding wygodny, wyraźny hover i focus ring.
- **Card** — `rounded-xl`, `border`, subtelny cień (`shadow-sm` → `shadow-md` na hover dla klikalnych).
- **Accordion** — do FAQ. Płynne rozwijanie, ikona +/− lub chevron.
- **Input / Textarea / Select** — spójne obramowania, focus w kolorze `accent`, czytelne labelki.
- **Badge / Tag** — do kategorii (realizacje, blog) i wyróżnień produktów.
- **Tabs** — do zakładek na karcie produktu.
---
## Wspólne komponenty własne (`components/common/`)
- **SectionHeading** — eyebrow (mały tekst nad), H2, opcjonalny podtytuł. Wyśrodkowany lub do lewej.
- **CTAButton** — przycisk z ikoną, wariant cta, używany w hero i banerach.
- **StatCounter** — duża liczba + podpis (np. „3500 realizacji").
- **IconCard** — ikona + tytuł + opis + opcjonalny link. Baza dla siatek usług.
- **StepItem** — numer + tytuł + opis. Baza dla procesów krok-po-kroku.
- **Placeholder** — szary blok z ikoną i opisem zamiast docelowego zdjęcia.
---
## Stany i interakcje
- Hover: subtelne podniesienie cienia / zmiana koloru, transition 150–200ms.
- Focus: widoczny ring w kolorze `accent` (dostępność).
- Loading: skeleton dla list (sklep, blog).
- Puste stany: czytelny komunikat + CTA (np. pusty koszyk).
---
## Zasada nadrzędna
Design ma wyglądać jak zaprojektowany przez człowieka: spójny, czysty, z oddechem.
Unikaj efektu „szablonu AI": przeładowania gradientami, zbyt wielu kolorów, ciasnych sekcji,
losowych cieni. Mniej, ale konsekwentnie.
+62
View File
@@ -0,0 +1,62 @@
# 03 — SEO
Zasady SEO dla całego projektu. Stosuj na każdej stronie.
---
## Metadata (Next.js Metadata API)
- Każda strona eksportuje `metadata` (statyczne) lub `generateMetadata` (dynamiczne: blog, produkt).
- W `app/layout.tsx`: `metadataBase`, domyślny `title.template` (np. `%s | Nazwa Firmy`),
domyślny opis, OpenGraph bazowy, `lang="pl"`.
- Każda strona nadpisuje `title` i `description` własnymi, unikalnymi wartościami.
### Wzorce title/description (przykłady do uzupełnienia nazwą firmy/miastem)
| Strona | Title | Description (do ~155 znaków) |
|--------|-------|------------------------------|
| Główna | Klimatyzacja, pompy ciepła i usługi domowe | Montaż klimatyzacji, pompy ciepła, remonty i hydraulika. Dobór, montaż i serwis. Darmowa konsultacja. |
| Klimatyzacja | Montaż klimatyzacji — dobór, instalacja, serwis | Profesjonalny montaż klimatyzacji split i multisplit. Cennik, dobór mocy, gwarancja i serwis. |
| Pompy ciepła | Pompy ciepła — montaż i dofinansowanie | Dobór i montaż pomp ciepła. Niższe rachunki, dotacje, pełen serwis. Sprawdź ofertę. |
| Usługi domowe | Usługi domowe — remonty, hydraulika, naprawy | Remonty i wykończenia, usługi hydrauliczne, serwis lodówek i drobne naprawy w jednym miejscu. |
| Remonty | Remonty i wykończenia wnętrz | Remonty mieszkań, łazienek i kuchni. Terminowo, czysto, z gwarancją. Bezpłatna wycena. |
| Hydraulika | Usługi hydrauliczne — instalacje i awarie | Instalacje wod-kan, naprawy, montaż armatury i szybka pomoc przy awariach. |
| Serwis AGD | Serwis lodówek i urządzeń chłodniczych | Naprawa lodówek, zamrażarek i witryn chłodniczych. Dojazd, diagnoza, gwarancja na naprawę. |
| Realizacje | Nasze realizacje | Zobacz wykonane montaże klimatyzacji, pompy ciepła i remonty. Portfolio z całego regionu. |
| Blog | Blog i poradniki | Porady o klimatyzacji, pompach ciepła i remontach. Jak dobrać, zamontować i użytkować. |
| O nas | O nas | Poznaj naszą firmę, doświadczenie i certyfikaty. Klimatyzacja i usługi domowe z gwarancją jakości. |
| Kontakt | Kontakt | Skontaktuj się z nami — telefon, e-mail, formularz. Darmowa konsultacja i wycena. |
---
## Struktura nagłówków
- Dokładnie jeden `<h1>` na stronę (główny nagłówek hero).
- Sekcje używają `<h2>`, podsekcje `<h3>`. Nie pomijaj poziomów.
- Nagłówki opisowe i z frazami kluczowymi, ale naturalne (nie keyword stuffing).
---
## Dane strukturalne JSON-LD
Wstaw jako `<script type="application/ld+json">` (przez komponent lub w layout/page).
- **LocalBusiness** — na stronie głównej i kontaktowej: nazwa, adres, telefon, godziny otwarcia,
obszar działania, `priceRange`, link do strony.
- **Service** — na stronach usługowych (klimatyzacja, pompy ciepła, remonty, hydraulika, serwis AGD):
typ usługi, opis, dostawca.
- **Product** + **Offer** — na karcie produktu: nazwa, opis, cena, dostępność, marka.
- **BlogPosting** — na stronie wpisu: tytuł, data, autor, obraz.
- **BreadcrumbList** — na stronach zagnieżdżonych (usługi domowe/…, sklep/…, blog/…).
- **FAQPage** — na stronach z sekcją FAQ (klimatyzacja, pompy ciepła, usługi).
---
## Pozostałe
- `app/sitemap.ts` — generuj z listy stron statycznych + dynamicznych (produkty, wpisy).
- `app/robots.ts` — zezwól na indeksację, wskaż sitemap.
- Obrazy: zawsze `alt` opisowy. OG image per kluczowa strona (`public/og/`).
- URL-e: czyste, po polsku bez znaków diakrytycznych (np. `/uslugi-domowe/hydraulika`).
- `lang="pl"` w html. Canonical przez `metadataBase` + ścieżki.
- Wydajność jako element SEO: dobre Core Web Vitals (LCP, CLS, INP) — patrz zasady wydajności w AGENTS.md.
+83
View File
@@ -0,0 +1,83 @@
# 04 — Layouty i nawigacja
Wspólne elementy obecne na wszystkich stronach. Buduj je raz, w `components/layout/`, i reużywaj.
---
## Header (`components/layout/Header.tsx`)
Sticky, biały (lub granatowy — do wyboru, spójnie), z cieniem po scrollu.
**Układ (desktop):**
- Lewa: logo (link do `/`).
- Środek: menu główne.
- Prawa: ikona wyszukiwarki, ikona konta, ikona koszyka (z licznikiem), przycisk CTA „Darmowa konsultacja".
**Menu główne:**
1. **Klimatyzacja** ▾ (dropdown — `NavDropdown`)
- Kategorie: Klimatyzatory ścienne, Multisplit, Przenośne, Kasetonowe, Konsolowe
- Usługi: Montaż klimatyzacji, Serwis i przeglądy
2. **Pompy ciepła** (link do `/pompy-ciepla`)
3. **Usługi domowe** ▾ (dropdown)
- Remonty i wykończenia, Hydraulika, Serwis AGD/lodówki, Drobne naprawy
4. **Realizacje** (`/realizacje`)
5. **Blog** (`/blog`)
6. **O nas** (`/o-nas`)
7. **Kontakt** (`/kontakt`)
**Dropdown (`NavDropdown`):** pojawia się na hover/focus, panel z linkami w kolumnach, dostępny
z klawiatury (Escape zamyka, focus trap niepotrzebny ale focusable linki).
**Mobile (`MobileMenu`):** hamburger → pełnoekranowe lub wysuwane menu z rozwijanymi sekcjami
(Klimatyzacja, Usługi domowe jako akordeony). CTA „Darmowa konsultacja" widoczne na dole.
Numer telefonu klikalny.
---
## Footer (`components/layout/Footer.tsx`)
Granatowe tło (`primary`), jasny tekst. 4 kolumny:
1. **Firma** — logo, krótki opis, adres, NIP, telefon (klikalny), godziny pracy.
2. **Usługi** — linki: Klimatyzacja, Pompy ciepła, Remonty, Hydraulika, Serwis AGD, Sklep.
3. **Informacje** — O nas, Realizacje, Blog, Regulamin, Polityka prywatności, Reklamacje, Kontakt.
4. **Twoje konto** — Koszyk, Logowanie, Rejestracja, Zamówienia.
**Pasek dolny:** copyright + rok (dynamiczny), ikony social media, drobne oznaczenia zaufania.
---
## TrustBar (`components/layout/TrustBar.tsx`)
Wąski pasek nad stopką (lub pod hero na stronie głównej). 4–5 elementów z ikonami:
- Szybki termin realizacji
- X lat doświadczenia
- Gwarancja
- Raty 0%
- Certyfikaty / opinie Google
Układ poziomy desktop, zawijany na mobile.
---
## Root layout (`app/layout.tsx`)
- `<html lang="pl">`, font przez `next/font`, `globals.css`.
- Renderuje `<Header />`, `{children}`, `<Footer />`.
- Bazowe `metadata` (template title, opis, OG) — patrz `docs/specs/03-seo.md`.
- JSON-LD LocalBusiness może iść tu lub na stronie głównej.
---
## Layout stron formalnych (`app/(formalne)/layout.tsx`)
Prosty, jednokolumnowy: nagłówek tytułu + treść tekstowa (`prose`), opcjonalny spis treści
z kotwicami po lewej na dłuższych stronach. Ten sam Header/Footer co reszta.
---
## Wspólny komponent CTA (`components/sections/CtaBanner.tsx`)
Powtarzalny baner końcowy: nagłówek („Masz pytania? Umów darmową konsultację"), podtytuł,
przycisk CTA + numer telefonu. Tło `primary` lub `accent-light`. Używany na końcu większości stron
(przyjmuje propsy: tytuł, opis, tekst przycisku).
+91
View File
@@ -0,0 +1,91 @@
# 05 — Model danych i mock content
Dane trzymane w `content/` jako typowane pliki TS. Typy w `types/`. Bez backendu na tym etapie.
---
## Typy (`types/`)
### Product (`types/product.ts`)
```ts
type Product = {
slug: string;
name: string;
brand: string;
category: "scienne" | "multisplit" | "przenosne" | "kasetonowe" | "konsolowe";
power: number; // kW
price: number; // cena urządzenia (brutto)
priceWithInstall: number; // cena z montażem (8% VAT)
variants?: { label: string; power: number; price: number }[];
image: string; // placeholder na razie
features: string[]; // np. ["Wi-Fi", "jonizacja", "grzanie"]
heating: boolean;
description: string;
specs: Record<string, string>; // dane techniczne (klucz: wartość)
};
```
### Project / realizacja (`types/project.ts`)
```ts
type Project = {
slug: string;
title: string;
category: "klimatyzacja" | "pompy-ciepla" | "remonty" | "hydraulika";
location: string; // np. "Wrocław"
image: string;
images?: string[]; // galeria
description: string;
scope?: string[]; // zakres prac
beforeAfter?: { before: string; after: string }; // dla remontów
};
```
### Post / wpis blogowy (`types/post.ts`)
```ts
type Post = {
slug: string;
title: string;
category: "klimatyzacja" | "pompy-ciepla" | "remonty" | "hydraulika" | "porady";
excerpt: string;
date: string; // ISO
author: string;
image: string;
content: string; // markdown lub HTML — render w [slug]
featured?: boolean;
};
```
### FAQ (`types/faq.ts`)
```ts
type FaqItem = { question: string; answer: string };
```
### Service step / krok procesu
```ts
type ProcessStep = { number: number; title: string; description: string; icon?: string };
```
---
## Mock content (`content/`)
Wygeneruj realistyczne, ale przykładowe dane (oznacz komentarzem `// MOCK`):
- **`products.ts`** — ok. 8 klimatyzatorów różnych marek i kategorii, z wariantami mocy i cenami.
- **`projects.ts`** — ok. 6 realizacji w różnych kategoriach (w tym 1–2 z before/after dla remontów).
- **`posts.ts`** — ok. 4 wpisy blogowe (1 oznaczony `featured`), z krótką treścią.
- **`faq.ts`** — zestawy FAQ per temat: klimatyzacja (8–10 pytań), pompy ciepła, remonty, hydraulika, serwis AGD.
- **`services.ts`** — definicje 6 usług na stronę główną (tytuł, opis, ikona, link).
- **`process.ts`** — kroki procesów (montaż klimatyzacji, wdrożenie pompy, remont, zgłoszenie serwisu).
- **`company.ts`** — dane firmy: nazwa, adres, NIP, telefon, e-mail, godziny, social, statystyki
(lata, realizacje, miasta), certyfikaty. Użyj placeholderów, oznacz `// TODO: dane firmy`.
- **`pricing.ts`** — pozycje cennika montażu (split, multisplit, usługi dodatkowe) jak w tabeli na stronie klimatyzacji.
---
## Zasady
- Dane importowane do stron przez funkcje pomocnicze w `lib/` (np. `getProducts()`, `getProductBySlug()`).
- `generateStaticParams` dla `blog/[slug]` i `sklep/[slug]` korzysta z tych danych.
- Ceny i treści to placeholdery — wyraźnie oznaczone, łatwe do podmiany przez właściciela.
- Nie wymyślaj prawdziwych danych firmy (adres, NIP) — zostaw oznaczone pola do uzupełnienia.