14 blog post schedule
This commit is contained in:
69
src/app/(main)/(marketing)/learn/[pillar]/page.tsx
Normal file
69
src/app/(main)/(marketing)/learn/[pillar]/page.tsx
Normal file
@@ -0,0 +1,69 @@
|
||||
import { notFound } from "next/navigation";
|
||||
import Link from "next/link";
|
||||
import Script from "next/script";
|
||||
import { pillarMeta } from "@/lib/pillar-data";
|
||||
import { getPostsByPillar } from "@/lib/content";
|
||||
import type { PillarKey } from "@/lib/types";
|
||||
import { pillarPageSchema, faqPageSchema } from "@/lib/schema";
|
||||
import { FAQSection } from "@/components/aeo/FAQSection";
|
||||
import { AnswerBox } from "@/components/aeo/AnswerBox";
|
||||
|
||||
export function generateMetadata({ params }: { params: { pillar: string } }) {
|
||||
const meta = pillarMeta.find(p => p.key === params.pillar);
|
||||
if (!meta) return {};
|
||||
return {
|
||||
title: `${meta.title} - Ultimate Guide | QR Master`,
|
||||
description: meta.description
|
||||
};
|
||||
}
|
||||
|
||||
export function generateStaticParams() {
|
||||
return pillarMeta.map((pillar) => ({
|
||||
pillar: pillar.key,
|
||||
}));
|
||||
}
|
||||
|
||||
export default function PillarPage({ params }: { params: { pillar: PillarKey } }) {
|
||||
const meta = pillarMeta.find(p => p.key === params.pillar);
|
||||
if (!meta) return notFound();
|
||||
|
||||
const posts = getPostsByPillar(meta.key);
|
||||
const jsonLd = pillarPageSchema(meta, posts);
|
||||
const faqLd = meta.miniFaq ? faqPageSchema(meta.miniFaq) : null;
|
||||
|
||||
return (
|
||||
<main className="container mx-auto max-w-5xl py-12 px-4 space-y-10">
|
||||
<Script id="ld-pillar" type="application/ld+json" strategy="afterInteractive"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }} />
|
||||
{faqLd && (
|
||||
<Script id="ld-pillar-faq" type="application/ld+json" strategy="afterInteractive"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(faqLd) }} />
|
||||
)}
|
||||
|
||||
<header className="space-y-4 max-w-3xl">
|
||||
<div className="text-sm font-medium text-gray-500 hover:text-gray-700">
|
||||
<Link href="/learn">Learn</Link> → <span className="text-gray-900">{meta.title}</span>
|
||||
</div>
|
||||
<h1 className="text-4xl md:text-5xl font-extrabold text-gray-900">{meta.title}</h1>
|
||||
<p className="text-xl text-gray-600">{meta.description}</p>
|
||||
</header>
|
||||
|
||||
<AnswerBox html={meta.quickAnswer} />
|
||||
|
||||
<section className="space-y-6">
|
||||
<h2 className="text-2xl font-bold text-gray-900">Guides & Articles</h2>
|
||||
<div className="grid md:grid-cols-2 gap-6">
|
||||
{posts.map(p => (
|
||||
<Link key={p.slug} href={`/blog/${p.slug}`} className="group block rounded-xl border border-gray-200 bg-white p-6 shadow-sm hover:shadow-md hover:border-blue-200 transition-all">
|
||||
<div className="text-xs text-gray-400 mb-2">{p.date}</div>
|
||||
<div className="text-lg font-bold text-gray-900 mb-2 group-hover:text-blue-700">{p.title}</div>
|
||||
<div className="text-sm text-gray-600 line-clamp-2">{p.description}</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{!!meta.miniFaq?.length && <FAQSection items={meta.miniFaq} title={`${meta.title} FAQ`} />}
|
||||
</main>
|
||||
);
|
||||
}
|
||||
54
src/app/(main)/(marketing)/learn/page.tsx
Normal file
54
src/app/(main)/(marketing)/learn/page.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
import Link from "next/link";
|
||||
import { pillarMeta } from "@/lib/pillar-data";
|
||||
import { getPublishedPosts } from "@/lib/content";
|
||||
|
||||
export const metadata = {
|
||||
title: "Learn QR Code Mastery | QR Master Hub",
|
||||
description: "Guides, use cases, tracking deep-dives, and security best practices for dynamic QR codes.",
|
||||
};
|
||||
|
||||
export default function LearnHubPage() {
|
||||
const posts = getPublishedPosts();
|
||||
// Sort by date descending
|
||||
const topLatest = [...posts].sort((a, b) => (new Date(a.datePublished).getTime() < new Date(b.datePublished).getTime() ? 1 : -1)).slice(0, 6);
|
||||
|
||||
return (
|
||||
<main className="container mx-auto max-w-5xl py-12 px-4 space-y-12">
|
||||
<header className="space-y-4 max-w-3xl">
|
||||
<h1 className="text-4xl md:text-5xl font-extrabold text-gray-900 tracking-tight">QR Code Knowledge Hub</h1>
|
||||
<p className="text-xl text-gray-600">
|
||||
Master the art of QR codes. Explore our expert guides on generation, tracking, security, and marketing strategies.
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-6">Topic Pillars</h2>
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{pillarMeta.sort((a, b) => a.order - b.order).map(p => (
|
||||
<Link key={p.key} href={`/learn/${p.key}`} className="group block h-full rounded-2xl border border-gray-200 bg-white p-6 shadow-sm hover:shadow-md hover:border-blue-200 transition-all">
|
||||
<div className="text-sm font-semibold text-blue-600 uppercase tracking-wide mb-2 opacity-80 group-hover:opacity-100">Pillar</div>
|
||||
<div className="text-2xl font-bold text-gray-900 mb-2 group-hover:text-blue-700">{p.title}</div>
|
||||
<div className="text-gray-600">{p.description}</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-6">Latest Guides</h2>
|
||||
<div className="grid md:grid-cols-2 gap-6">
|
||||
{topLatest.map(p => (
|
||||
<Link key={p.slug} href={`/blog/${p.slug}`} className="group block rounded-2xl border border-gray-200 bg-white p-6 shadow-sm hover:shadow-md hover:border-blue-200 transition-all">
|
||||
<div className="flex justify-between items-center mb-3">
|
||||
<div className="text-xs font-semibold px-2 py-1 rounded bg-gray-100 text-gray-600">{p.pillar?.toUpperCase() || 'GUIDE'}</div>
|
||||
<div className="text-xs text-gray-400">{p.date}</div>
|
||||
</div>
|
||||
<div className="text-xl font-bold text-gray-900 mb-2 group-hover:text-blue-700 line-clamp-2">{p.title}</div>
|
||||
<div className="text-gray-600 line-clamp-2">{p.description}</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user