From d49c9aa225f416a0b94cb1023e6bc7a37c438e29 Mon Sep 17 00:00:00 2001 From: egecankomur Date: Thu, 4 Jun 2026 07:15:18 +0300 Subject: [PATCH] =?UTF-8?q?feat:=20SEO=20altyap=C4=B1s=C4=B1=20+=20admin?= =?UTF-8?q?=20edit=C3=B6r/favicon/men=C3=BC=20d=C3=BCzeltmeleri?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Admin & site: - @tailwindcss/typography ekle → editör ve yayın içeriği prose stilleriyle düzgün render - Favicon: logo.png'den kare app/icon.png + apple-icon.png, varsayılan favicon.ico kaldırıldı - SEO keyword: seo_settings.default_keywords + seo_pages.keywords + buildMetadata birleştirme - Menü düzeni admin'den yönetilebilir (site_settings.nav_items, /admin/menu, header & mobile-menu refactor) SEO: - app/sitemap.ts (statik + blog/hizmet/çözüm/proje/sektör dinamik) - app/robots.ts (sitemap ref + /admin,/api disallow) - app/llms.txt/route.ts (AI/LLM rehberi) - BlogPosting/Service/FAQ/Article JSON-LD wire (json-ld bileşenleri bağlandı) - buildMetadata: blog/proje OG görseli + type article + keywords birleştirme düzeltmesi - blog tags → keyword --- .gitignore | 3 + app/(site)/blog/[slug]/page.tsx | 3 + app/(site)/hizmetler/[slug]/page.tsx | 3 + app/(site)/projeler/[slug]/page.tsx | 2 + app/admin/(protected)/menu/form.tsx | 137 ++++++++++++++++++ app/admin/(protected)/menu/page.tsx | 19 +++ app/admin/(protected)/seo/page-form.tsx | 8 ++ app/admin/(protected)/seo/page.tsx | 11 ++ app/apple-icon.png | Bin 0 -> 13975 bytes app/favicon.ico | Bin 25931 -> 0 bytes app/globals.css | 1 + app/icon.png | Bin 0 -> 44383 bytes app/layout.tsx | 3 +- app/llms.txt/route.ts | 96 +++++++++++++ app/robots.ts | 14 ++ app/sitemap.ts | 53 +++++++ components/admin/sidebar.tsx | 2 + components/header.tsx | 180 ++++++++++++------------ components/json-ld.tsx | 45 ++++++ components/mobile-menu.tsx | 106 +++++++------- lib/admin-actions.ts | 30 ++++ lib/nav.ts | 119 ++++++++++++++++ lib/seo.ts | 45 +++++- lib/types.ts | 5 + package-lock.json | 45 +++++- package.json | 1 + 26 files changed, 780 insertions(+), 151 deletions(-) create mode 100644 app/admin/(protected)/menu/form.tsx create mode 100644 app/admin/(protected)/menu/page.tsx create mode 100644 app/apple-icon.png delete mode 100644 app/favicon.ico create mode 100644 app/icon.png create mode 100644 app/llms.txt/route.ts create mode 100644 app/robots.ts create mode 100644 app/sitemap.ts create mode 100644 lib/nav.ts diff --git a/.gitignore b/.gitignore index 27bb1dd..07dbc26 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,6 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts + +# SEO audit çıktıları (repoya girmesin) +seo-audit/ diff --git a/app/(site)/blog/[slug]/page.tsx b/app/(site)/blog/[slug]/page.tsx index c1749d1..af80d8b 100644 --- a/app/(site)/blog/[slug]/page.tsx +++ b/app/(site)/blog/[slug]/page.tsx @@ -6,6 +6,7 @@ import { ArrowLeft, Calendar } from "lucide-react"; import { renderContent } from "@/lib/content-render"; import { getPostBySlug } from "@/lib/data"; import { buildMetadata } from "@/lib/seo"; +import { BlogPostingLd } from "@/components/json-ld"; import { ContentSidebar } from "@/components/content-sidebar"; export async function generateMetadata({ @@ -19,6 +20,7 @@ export async function generateMetadata({ return buildMetadata(`/blog/${slug}`, { title: post.seo_title || post.title, description: post.seo_description || post.excerpt || undefined, + keywords: post.tags ?? undefined, openGraph: { title: post.seo_title || post.title, description: post.seo_description || post.excerpt || undefined, @@ -44,6 +46,7 @@ export default async function BlogPostPage({ return (
+ + +
diff --git a/app/(site)/projeler/[slug]/page.tsx b/app/(site)/projeler/[slug]/page.tsx index 9059f5b..6972e09 100644 --- a/app/(site)/projeler/[slug]/page.tsx +++ b/app/(site)/projeler/[slug]/page.tsx @@ -7,6 +7,7 @@ import { renderContent } from "@/lib/content-render"; import { getProjectBySlug, listProjects } from "@/lib/data"; import { buildMetadata } from "@/lib/seo"; import { Gallery } from "@/components/gallery"; +import { ArticleLd } from "@/components/json-ld"; import { TrendingUp } from "lucide-react"; import type { ProjectMetric } from "@/lib/types"; @@ -74,6 +75,7 @@ export default async function ProjectDetailPage({ return ( <> +
(initial); + + function move(index: number, dir: -1 | 1) { + const target = index + dir; + if (target < 0 || target >= items.length) return; + setItems((prev) => { + const next = [...prev]; + [next[index], next[target]] = [next[target], next[index]]; + return next; + }); + } + + function toggleVisible(index: number) { + setItems((prev) => + prev.map((it, i) => + i === index ? { ...it, visible: !it.visible } : it, + ), + ); + } + + function setLabel(index: number, value: string) { + setItems((prev) => + prev.map((it, i) => (i === index ? { ...it, label: value } : it)), + ); + } + + const payload = serializeNavItems( + items.map((i) => ({ key: i.key, visible: i.visible, label: i.label })), + ); + + return ( +
+ + +
    + {items.map((item, i) => ( +
  • + + +
    + + +
    + + setLabel(i, e.target.value)} + className="min-w-0 flex-1 rounded-lg border border-[var(--border)] bg-white px-3 py-1.5 text-sm outline-none transition focus:border-[var(--sky)] focus:ring-2 focus:ring-[var(--sky)]/20" + /> + + + {item.href} + + + {item.mega && ( + + Mega menü + + )} + + +
  • + ))} +
+ +

+ Sıralama ok tuşlarıyla değişir. Göz simgesiyle bir öğeyi menüden + gizleyebilirsiniz. “Hizmetler” öğesi mega menü olarak + açılır. +

+ + + + Menüyü kaydet + + +
+
+ ); +} diff --git a/app/admin/(protected)/menu/page.tsx b/app/admin/(protected)/menu/page.tsx new file mode 100644 index 0000000..128f3e3 --- /dev/null +++ b/app/admin/(protected)/menu/page.tsx @@ -0,0 +1,19 @@ +import { PageHeader } from "@/components/admin/form"; +import { getSiteSettings } from "@/lib/data"; +import { resolveNavItems } from "@/lib/nav"; +import { MenuForm } from "./form"; + +export default async function MenuAdminPage() { + const settings = await getSiteSettings(); + const items = resolveNavItems(settings?.nav_items); + + return ( +
+ + +
+ ); +} diff --git a/app/admin/(protected)/seo/page-form.tsx b/app/admin/(protected)/seo/page-form.tsx index 668ad22..f64ea46 100644 --- a/app/admin/(protected)/seo/page-form.tsx +++ b/app/admin/(protected)/seo/page-form.tsx @@ -40,6 +40,14 @@ export function SeoPageForm({ row }: { row?: SeoPageRow }) { rows={3} defaultValue={row?.description} /> +