Files
Paweł Domański eb09da9e4d Integracja Directus LabAI, naprawa Schema.org, poprawki UI
- Zmiana kolekcji Directus z Laboratorium_AI na LabAI
- Usunięcie fallbacku na fake dane — brak wpisów = komunikat
- revalidate=0 na stronie głównej (zawsze świeże dane)
- BlogPosting przeniesiony do @graph (poprawna spec Schema.org)
- Inbox Libredesk zaktualizowany
- Hero image-wrap powiększony (scale 1.56)
- Dokumentacja projektu w CLAUDE.md

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-07-05 13:14:43 +02:00

220 lines
7.3 KiB
Markdown

## SEO — JSON-LD Schema.org
Każda nowa strona (`src/app/*/page.jsx`) musi mieć odpowiedni JSON-LD w `<head>`.
- Strona główna → `WebSite` + `WebPage` + `Organization` + `blogPost[]` (komponent `SchemaOrg` w `layout.jsx`)
- Strona artykułu → `BlogPosting` (headline, url, datePublished, author, image)
- Strona kontakt → `ContactPage`
- Strona "wkrótce" → `WebPage` z `name` i `description`
JSON-LD idzie do `<head>` przez `<script type="application/ld+json" dangerouslySetInnerHTML=.../>` — nie przez `useEffect`. Dane do schematu pobieraj po stronie serwera (Server Component).
## Coding Guidelines (Karpathy)
Behavioral guidelines to reduce common LLM coding mistakes.
**Tradeoff:** Bias toward caution over speed. For trivial tasks, use judgment.
### 1. Think Before Coding
**Don't assume. Don't hide confusion. Surface tradeoffs.**
Before implementing:
- State assumptions explicitly. If uncertain, ask.
- If multiple interpretations exist, present them — don't pick silently.
- If a simpler approach exists, say so. Push back when warranted.
- If something is unclear, stop. Name what's confusing. Ask.
### 2. Simplicity First
**Minimum code that solves the problem. Nothing speculative.**
- No features beyond what was asked.
- No abstractions for single-use code.
- No "flexibility" or "configurability" that wasn't requested.
- No error handling for impossible scenarios.
- If you write 200 lines and it could be 50, rewrite it.
Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify.
### 3. Surgical Changes
**Touch only what you must. Clean up only your own mess.**
When editing existing code:
- Don't "improve" adjacent code, comments, or formatting.
- Don't refactor things that aren't broken.
- Match existing style, even if you'd do it differently.
- If you notice unrelated dead code, mention it — don't delete it.
When your changes create orphans:
- Remove imports/variables/functions that YOUR changes made unused.
- Don't remove pre-existing dead code unless asked.
The test: Every changed line should trace directly to the user's request.
### 4. Goal-Driven Execution
**Define success criteria. Loop until verified.**
Transform tasks into verifiable goals:
- "Add validation" → "Write tests for invalid inputs, then make them pass"
- "Fix the bug" → "Write a test that reproduces it, then make it pass"
- "Refactor X" → "Ensure tests pass before and after"
For multi-step tasks, state a brief plan:
```
1. [Step] → verify: [check]
2. [Step] → verify: [check]
3. [Step] → verify: [check]
```
---
## Projekt: dexterlab.pl website
### Stack
- **Next.js 14** (App Router) — `src/app/`
- **React 18** — Server Components domyślnie, `'use client'` tylko gdy trzeba
- **Directus CMS** — `https://cms.dexterlab.pl` (headless, REST API)
- **CSS** — własny, w `src/index.css`
- **Fonty** — Inter przez `next/font/google`
> **Uwaga:** W katalogu istnieje też stary `src/App.jsx` i `src/main.jsx` (pozostałości po Vite). Są nieużywane — Next.js korzysta wyłącznie z `src/app/`.
---
### Struktura katalogów
```
src/
├── app/ # Next.js App Router
│ ├── layout.jsx # Root layout: Nav, Footer, Cookie, Schema, skrypty
│ ├── page.jsx # Strona główna (/)
│ ├── produkty/page.jsx # Strona produktów (/produkty)
│ ├── kontakt/page.jsx # Strona kontaktu (/kontakt)
│ └── dla-zaawansowanych/ # Placeholder "coming soon"
│ └── page.jsx
├── components/
│ ├── Nav.jsx # Nawigacja (client — używa usePathname)
│ ├── BentoCard.jsx # Karta artykułu w siatce Bento
│ ├── BentoSlideshow.jsx # Slideshow featured artykułów
│ ├── ProductCard.jsx # Karta produktu na /produkty
│ ├── SubscribeBox.jsx # Formularz zapisu do newslettera
│ ├── CookieBanner.jsx # Banner RODO
│ ├── Footer.jsx # Stopka
│ └── SchemaOrg.jsx # JSON-LD (server component, async)
├── sections/
│ ├── Hero.jsx # Sekcja hero na stronie głównej
│ ├── Benefits.jsx # Sekcja korzyści
│ ├── ProductsPreview.jsx # Podgląd produktów na stronie głównej
│ ├── ComingSoon.jsx # Placeholder dla niegotowych stron
│ └── ContactPage.jsx # Formularz kontaktowy
├── lib/
│ ├── directus.js # Fetch z Directus + mapowanie danych
│ └── productSchema.js # Generuje JSON-LD schema.org dla produktów
└── data/
└── content.js # Statyczne dane: news, videos (sidebar)
```
---
### Strony
| URL | Plik | Dane |
|-----|------|------|
| `/` | `src/app/page.jsx` | Directus `LabAI` (artykuły + slideshow) |
| `/produkty` | `src/app/produkty/page.jsx` | Directus `products` |
| `/kontakt` | `src/app/kontakt/page.jsx` | statyczna |
| `/dla-zaawansowanych` | `src/app/dla-zaawansowanych/page.jsx` | Coming soon |
---
### Directus CMS
**URL:** `https://cms.dexterlab.pl`
#### Kolekcje
| Kolekcja | Używana przez | Filtr |
|----------|---------------|-------|
| `LabAI` | `src/lib/directus.js` | `status = published` |
| `products` | `src/app/produkty/page.jsx` | `site = labai.pro`, `status = published` |
#### Pola kolekcji `LabAI`
| Pole | Opis |
|------|------|
| `Title` | Tytuł artykułu |
| `Badge` | HOT / NEW / TUTORIAL / TIPS |
| `Category` | Kategoria (string) |
| `Cover_Image` | UUID — obrazek przez `${DIRECTUS_URL}/assets/{id}` |
| `Is_Featured` | Boolean — czy w slideshow |
| `status` | `published` = widoczny |
#### Pola kolekcji `products`
| Pole | Opis |
|------|------|
| `title` | Nazwa produktu |
| `short_description` | Opis |
| `price` | Cena bazowa |
| `discount_price` | Cena promocyjna (opcjonalne) |
| `currency` | np. `PLN` |
| `url` | Link zakupowy |
| `product_image` | UUID obrazka |
| `sku` | Opcjonalne |
| `site` | `labai.pro` |
| `status` | `published` |
| `sort` | Kolejność wyświetlania |
#### Uprawnienia
Kolekcje `LabAI` i `products` muszą mieć **Public role → Read** włączone w Directus. Bez tego API zwraca 403.
---
### Cache / revalidacja
| Strona | `revalidate` | Zachowanie |
|--------|-------------|------------|
| `/` | `0` | Zawsze świeże (fetch przy każdym requescie) |
| `/produkty` | `300` | ISR — odświeżenie co 5 minut |
Gdy ruch urośnie: wdrożyć on-demand revalidation przez `POST /api/revalidate` + webhook w Directus.
---
### Zewnętrzne integracje
| Serwis | Gdzie | Co robi |
|--------|-------|---------|
| Libredesk | `src/app/layout.jsx` | Widget czatu (inbox: `bffd72d7-a528-42ca-bfed-377670d49364`) |
| Umami | `src/app/layout.jsx` | Analityka (`stat.dexterlab.pl`) |
| Google Fonts | `layout.jsx` (next/font) | Font Inter |
---
### Uruchamianie lokalnie
```bash
npm run dev # http://localhost:3000
npm run build # build produkcyjny
npm run start # serwer produkcyjny
```
---
### Dodawanie nowej strony
1. Utwórz `src/app/<slug>/page.jsx` — Server Component (async)
2. Dodaj `export const metadata = { title, description }`
3. Jeśli pobiera dane z Directus — dodaj `export const revalidate = 0` lub `300`
4. Dodaj JSON-LD jeśli strona ma unikalny typ treści
5. Dodaj link w `src/components/Nav.jsx`