From 8d4dc8a6f1faa166641327e96004e790580be2ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Doma=C5=84ski?= Date: Sun, 5 Jul 2026 19:49:19 +0200 Subject: [PATCH] =?UTF-8?q?Strony=20artyku=C5=82=C3=B3w,=20sitemap,=20GA4,?= =?UTF-8?q?=20polityka=20prywatno=C5=9Bci?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Klikalne kafelki i slideshow → /blog/[slug] - Strona artykułu: cover fullwidth z parallax, tytuł nad obrazkiem - Schema.org BlogPosting na stronach postów - Dynamiczny sitemap.xml (artykuły + produkty z Directus, revalidate=0) - Google Analytics GA4 (G-7067BL7TDN) - Polityka prywatności /polityka-prywatnosci - CookieBanner z linkiem do polityki - Footer: działający link do polityki prywatności Co-Authored-By: Claude Sonnet 4.6 (1M context) --- package.json | 17 +++-- src/app/blog/[slug]/page.jsx | 76 ++++++++++++++++++++ src/app/layout.jsx | 2 + src/app/page.jsx | 1 + src/app/polityka-prywatnosci/page.jsx | 57 +++++++++++++++ src/app/sitemap.js | 50 ++++++++++++++ src/components/BentoCard.jsx | 16 +++-- src/components/BentoSlideshow.jsx | 12 +++- src/components/CookieBanner.jsx | 9 ++- src/components/Footer.jsx | 48 +++++++++++++ src/index.css | 99 +++++++++++++++++++++++++++ src/lib/directus.js | 13 ++++ 12 files changed, 382 insertions(+), 18 deletions(-) create mode 100644 src/app/blog/[slug]/page.jsx create mode 100644 src/app/polityka-prywatnosci/page.jsx create mode 100644 src/app/sitemap.js create mode 100644 src/components/Footer.jsx diff --git a/package.json b/package.json index abe3872..43cb484 100644 --- a/package.json +++ b/package.json @@ -1,21 +1,20 @@ { "name": "bento-website", "private": true, - "version": "0.0.0", - "type": "module", + "version": "0.1.0", "scripts": { - "dev": "vite", - "build": "vite build", - "preview": "vite preview" + "dev": "next dev", + "build": "next build", + "start": "next start" }, "dependencies": { + "next": "^14.2.0", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "react-markdown": "^10.1.0" }, "devDependencies": { "@types/react": "^18.2.66", - "@types/react-dom": "^18.2.22", - "@vitejs/plugin-react": "^4.2.1", - "vite": "^5.2.0" + "@types/react-dom": "^18.2.22" } } diff --git a/src/app/blog/[slug]/page.jsx b/src/app/blog/[slug]/page.jsx new file mode 100644 index 0000000..d928a65 --- /dev/null +++ b/src/app/blog/[slug]/page.jsx @@ -0,0 +1,76 @@ +import { notFound } from 'next/navigation' +import { fetchArticle } from '../../../lib/directus' + +const DIRECTUS_URL = 'https://cms.dexterlab.pl' +const BASE_URL = 'https://labai.pro' + +function blogPostingSchema(article) { + return { + '@context': 'https://schema.org', + '@type': 'BlogPosting', + '@id': `${BASE_URL}/blog/${article.Slug}`, + headline: article.Title, + url: `${BASE_URL}/blog/${article.Slug}`, + description: article.Excerpt || undefined, + datePublished: article.date_published || article.date_created, + dateModified: article.date_updated || article.date_published || article.date_created, + image: article.Cover_Image ? `${DIRECTUS_URL}/assets/${article.Cover_Image}` : undefined, + author: article.Author + ? { '@type': 'Person', name: article.Author } + : { '@type': 'Organization', name: 'Laboratorium AI' }, + publisher: { + '@type': 'Organization', + '@id': `${BASE_URL}/#organization`, + name: 'Laboratorium AI', + }, + mainEntityOfPage: { '@type': 'WebPage', '@id': `${BASE_URL}/blog/${article.Slug}` }, + } +} + +export const revalidate = 0 + +export async function generateMetadata({ params }) { + const article = await fetchArticle(params.slug) + if (!article) return {} + return { + title: `${article.Title} — Laboratorium AI`, + description: article.Excerpt || article.Title, + openGraph: { + title: article.Title, + images: article.Cover_Image ? [`${DIRECTUS_URL}/assets/${article.Cover_Image}`] : [], + }, + } +} + +export default async function ArticlePage({ params }) { + const article = await fetchArticle(params.slug) + if (!article) notFound() + + return ( +
+