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} /> +