Add Ghost CMS blog section (list + article pages)
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import { GhostPost, postExcerpt, formatDate, readingTime } from "@/lib/ghost";
|
||||
|
||||
/** Shared cover: real Ghost feature image, or a branded fallback when null. */
|
||||
function Cover({ post, sizes }: { post: GhostPost; sizes: string }) {
|
||||
if (post.feature_image) {
|
||||
return (
|
||||
<Image
|
||||
src={post.feature_image}
|
||||
alt={post.feature_image_alt || post.title}
|
||||
fill
|
||||
className="img-cover"
|
||||
sizes={sizes}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className="blog-card__placeholder" aria-hidden>
|
||||
<span>{(post.primary_tag?.name || post.title).charAt(0)}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function FeaturedBlogCard({ post }: { post: GhostPost }) {
|
||||
return (
|
||||
<Link href={`/blog/${post.slug}`} className="blog-feature">
|
||||
<div className="blog-feature__media">
|
||||
<Cover post={post} sizes="(max-width: 900px) 100vw, 640px" />
|
||||
</div>
|
||||
<div className="blog-feature__body">
|
||||
{post.primary_tag && <span className="blog-tag">{post.primary_tag.name}</span>}
|
||||
<h2 className="blog-feature__title">{post.title}</h2>
|
||||
<p className="blog-feature__excerpt">{postExcerpt(post, 220)}</p>
|
||||
<div className="blog-meta">
|
||||
<span>{formatDate(post.published_at)}</span>
|
||||
{readingTime(post) && <span className="blog-meta__dot">•</span>}
|
||||
{readingTime(post) && <span>{readingTime(post)}</span>}
|
||||
</div>
|
||||
<span className="link-arrow link-arrow--spaced-lg">Read article</span>
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
export function BlogCard({ post }: { post: GhostPost }) {
|
||||
return (
|
||||
<Link href={`/blog/${post.slug}`} className="blog-card">
|
||||
<div className="blog-card__media">
|
||||
<Cover post={post} sizes="(max-width: 640px) 100vw, 400px" />
|
||||
{post.primary_tag && <span className="blog-tag blog-tag--float">{post.primary_tag.name}</span>}
|
||||
</div>
|
||||
<div className="blog-card__body">
|
||||
<h3 className="blog-card__title">{post.title}</h3>
|
||||
<p className="blog-card__excerpt">{postExcerpt(post)}</p>
|
||||
<div className="blog-meta">
|
||||
<span>{formatDate(post.published_at)}</span>
|
||||
{readingTime(post) && <span className="blog-meta__dot">•</span>}
|
||||
{readingTime(post) && <span>{readingTime(post)}</span>}
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
@@ -10,6 +10,7 @@ const links = [
|
||||
{ href: "/about", label: "About" },
|
||||
{ href: "/events", label: "Events" },
|
||||
{ href: "/knowledge", label: "Knowledge" },
|
||||
{ href: "/blog", label: "Blog" },
|
||||
{ href: "/gallery", label: "Gallery" },
|
||||
{ href: "/why-join", label: "Why Join" },
|
||||
{ href: "/contact", label: "Contact" },
|
||||
|
||||
Reference in New Issue
Block a user