diff --git a/app/[locale]/cheatsheets/layout.tsx b/app/[locale]/cheatsheets/layout.tsx
new file mode 100644
index 0000000..cde6597
--- /dev/null
+++ b/app/[locale]/cheatsheets/layout.tsx
@@ -0,0 +1,50 @@
+import type { Metadata } from 'next';
+
+const BASE_URL = 'https://ayrisai.xyz';
+
+export const metadata: Metadata = {
+ title: 'Developer Cheatsheets & Quick Reference | ayris.tech',
+ description:
+ 'Free developer cheatsheets for Git, Next.js App Router, Docker, TypeScript, Python, SQL, and more. Quick-copy command references used in ayris.tech YouTube tutorials.',
+ keywords: [
+ 'developer cheatsheet', 'Git commands cheatsheet', 'Next.js cheatsheet',
+ 'Docker commands', 'TypeScript quick reference', 'SQL cheatsheet',
+ 'programming reference card', 'ayris.tech',
+ ],
+ alternates: {
+ canonical: `${BASE_URL}/en/cheatsheets`,
+ },
+ openGraph: {
+ title: 'Developer Cheatsheets & Quick Reference | ayris.tech',
+ description: 'Free copy-paste developer cheatsheets for Git, Next.js, Docker, TypeScript, and more.',
+ url: `${BASE_URL}/en/cheatsheets`,
+ type: 'website',
+ },
+};
+
+export default function CheatsheetsLayout({ children }: { children: React.ReactNode }) {
+ return (
+ <>
+
+ {children}
+ >
+ );
+}
diff --git a/app/[locale]/layout.tsx b/app/[locale]/layout.tsx
index 6908279..bc7f3ba 100644
--- a/app/[locale]/layout.tsx
+++ b/app/[locale]/layout.tsx
@@ -89,6 +89,43 @@ export default async function RootLayout({
className={`${jakartaSans.variable} ${jetbrainsMono.variable} dark h-full antialiased`}
>
+ {/* Organization + WebSite JSON-LD — global entity recognition */}
+
diff --git a/app/[locale]/lessons/[slug]/layout.tsx b/app/[locale]/lessons/[slug]/layout.tsx
new file mode 100644
index 0000000..e84c8ce
--- /dev/null
+++ b/app/[locale]/lessons/[slug]/layout.tsx
@@ -0,0 +1,110 @@
+import type { Metadata } from 'next';
+import { getLessonBySlug } from '@/lib/actions/lessonActions';
+
+const BASE_URL = 'https://ayrisai.xyz';
+
+interface Props {
+ params: Promise<{ locale: string; slug: string }>;
+}
+
+export async function generateMetadata({ params }: Props): Promise {
+ const { slug, locale } = await params;
+ const lesson = await getLessonBySlug(slug);
+
+ if (!lesson) {
+ return {
+ title: 'Lesson Not Found | ayris.tech',
+ };
+ }
+
+ const url = `${BASE_URL}/${locale}/lessons/${slug}`;
+ const description =
+ lesson.summary ||
+ `Watch the ${lesson.title} tutorial on ayris.tech YouTube. Download source code, read lesson notes, and grab the full project starter pack.`;
+
+ return {
+ title: lesson.title,
+ description,
+ keywords: [
+ ...(lesson.tags || []),
+ 'YouTube tutorial', 'source code download', 'ayris.tech', lesson.category,
+ ],
+ alternates: { canonical: url },
+ openGraph: {
+ title: lesson.title,
+ description,
+ url,
+ type: 'video.other',
+ images: lesson.thumbnailUrl
+ ? [{ url: lesson.thumbnailUrl, width: 1280, height: 720, alt: lesson.title }]
+ : [],
+ },
+ twitter: {
+ card: 'summary_large_image',
+ title: lesson.title,
+ description,
+ images: lesson.thumbnailUrl ? [lesson.thumbnailUrl] : [],
+ },
+ };
+}
+
+export default async function LessonDetailLayout({
+ children,
+ params,
+}: {
+ children: React.ReactNode;
+ params: Promise<{ locale: string; slug: string }>;
+}) {
+ const { slug, locale } = await params;
+ const lesson = await getLessonBySlug(slug);
+
+ const jsonLd = lesson
+ ? {
+ '@context': 'https://schema.org',
+ '@graph': [
+ {
+ '@type': 'VideoObject',
+ name: lesson.title,
+ description: lesson.summary || lesson.title,
+ thumbnailUrl: lesson.thumbnailUrl || '',
+ uploadDate: lesson.createdAt || new Date().toISOString(),
+ duration: lesson.duration
+ ? `PT${lesson.duration.replace(':', 'M')}S`
+ : undefined,
+ contentUrl: lesson.youtubeUrl || '',
+ embedUrl: lesson.youtubeId
+ ? `https://www.youtube.com/embed/${lesson.youtubeId}`
+ : undefined,
+ author: { '@type': 'Person', name: 'ayris.tech', url: BASE_URL },
+ publisher: {
+ '@type': 'Organization',
+ name: 'ayris.tech',
+ url: BASE_URL,
+ logo: { '@type': 'ImageObject', url: `${BASE_URL}/logo.jpeg` },
+ },
+ },
+ {
+ '@type': 'BreadcrumbList',
+ itemListElement: [
+ { '@type': 'ListItem', position: 1, name: 'Home', item: `${BASE_URL}/${locale}` },
+ { '@type': 'ListItem', position: 2, name: 'Lessons', item: `${BASE_URL}/${locale}/lessons` },
+ { '@type': 'ListItem', position: 3, name: lesson.title, item: `${BASE_URL}/${locale}/lessons/${slug}` },
+ ],
+ },
+ ],
+ }
+ : null;
+
+ return (
+ <>
+ {jsonLd && (
+
+ )}
+ {children}
+ >
+ );
+}
diff --git a/app/[locale]/lessons/layout.tsx b/app/[locale]/lessons/layout.tsx
new file mode 100644
index 0000000..5ef96f5
--- /dev/null
+++ b/app/[locale]/lessons/layout.tsx
@@ -0,0 +1,52 @@
+import type { Metadata } from 'next';
+
+const BASE_URL = 'https://ayrisai.xyz';
+
+export const metadata: Metadata = {
+ title: 'YouTube Lessons & Source Code | ayris.tech',
+ description:
+ 'Browse all ayris.tech YouTube tutorial source code, lesson notes, starter packages, and project downloads. Covering Next.js, React, Python, TypeScript, Tailwind CSS, AI, and more.',
+ keywords: [
+ 'Next.js tutorial source code', 'React tutorial download',
+ 'YouTube code resources', 'TypeScript tutorial',
+ 'Tailwind CSS examples', 'full-stack web development',
+ 'ayris.tech YouTube', 'Python AI tutorial',
+ ],
+ alternates: {
+ canonical: `${BASE_URL}/en/lessons`,
+ },
+ openGraph: {
+ title: 'YouTube Lessons & Source Code | ayris.tech',
+ description: 'Download source code and browse lesson notes for every ayris.tech YouTube tutorial.',
+ url: `${BASE_URL}/en/lessons`,
+ type: 'website',
+ },
+};
+
+export default function LessonsLayout({ children }: { children: React.ReactNode }) {
+ return (
+ <>
+ {/* WebSite + ItemList Schema for lesson listing */}
+
+ {children}
+ >
+ );
+}
diff --git a/app/[locale]/prompts/layout.tsx b/app/[locale]/prompts/layout.tsx
new file mode 100644
index 0000000..b8ec151
--- /dev/null
+++ b/app/[locale]/prompts/layout.tsx
@@ -0,0 +1,50 @@
+import type { Metadata } from 'next';
+
+const BASE_URL = 'https://ayrisai.xyz';
+
+export const metadata: Metadata = {
+ title: 'AI System Prompts & LLM Templates | ayris.tech',
+ description:
+ 'Curated AI system prompts and LLM agent templates for ChatGPT, Claude, and Gemini. Covering Next.js architecture, UI/UX design, Python automation, and full-stack development roles.',
+ keywords: [
+ 'AI system prompts', 'ChatGPT system prompt', 'Claude system prompt',
+ 'LLM agent template', 'AI coding assistant prompt',
+ 'Next.js AI prompt', 'Python AI agent prompt', 'Gemini prompt engineering',
+ ],
+ alternates: {
+ canonical: `${BASE_URL}/en/prompts`,
+ },
+ openGraph: {
+ title: 'AI System Prompts & LLM Templates | ayris.tech',
+ description: 'Battle-tested AI system prompts and LLM templates for ChatGPT, Claude, and Gemini.',
+ url: `${BASE_URL}/en/prompts`,
+ type: 'website',
+ },
+};
+
+export default function PromptsLayout({ children }: { children: React.ReactNode }) {
+ return (
+ <>
+
+ {children}
+ >
+ );
+}