From e5a59c51910434013aef35857e263c38032b0bf9 Mon Sep 17 00:00:00 2001 From: Mannu Date: Fri, 29 May 2026 10:06:14 +0530 Subject: [PATCH] feat(blog): 3-col layout, breadcrumbs, TOC + footer 3-col bottom bar MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Blog listing (/blog): - Breadcrumb: Home › Blog - Left sidebar: chronological timeline with dot + date + category badge - Right sidebar: "Browse by topic" category counts, quick reads, CTA card - Still single column on mobile (sidebars hidden) Blog post (/blog/[slug]): - Breadcrumb: Home › Blog › Post title - Left sidebar: numbered Table of Contents (section headings as anchor links) with "← All articles" back link below - Right sidebar: "More articles" list + "Filed under" category + CTA - scroll-mt-28 on headings so sticky nav doesn't cover anchor targets - Both back-to-listing links visible (sidebar + article footer) Footer bottom bar: - Split into 3-column grid: © left · privacy tagline center · ❤️ India right Co-Authored-By: Claude Sonnet 4.6 --- src/app/(marketing)/blog/[slug]/page.tsx | 352 ++++++++++++++++------- src/app/(marketing)/blog/page.tsx | 200 ++++++++++--- src/app/(marketing)/layout.tsx | 7 +- src/components/marketing/Breadcrumb.tsx | 32 +++ 4 files changed, 436 insertions(+), 155 deletions(-) create mode 100644 src/components/marketing/Breadcrumb.tsx diff --git a/src/app/(marketing)/blog/[slug]/page.tsx b/src/app/(marketing)/blog/[slug]/page.tsx index faaaa09..4d1c441 100644 --- a/src/app/(marketing)/blog/[slug]/page.tsx +++ b/src/app/(marketing)/blog/[slug]/page.tsx @@ -2,6 +2,17 @@ import type { Metadata } from "next"; import Link from "next/link"; import { notFound } from "next/navigation"; import { POSTS, getPost, formatDate } from "../posts"; +import { Breadcrumb } from "@/components/marketing/Breadcrumb"; + +// Turn a heading string into a URL-safe anchor ID +function slugifyHeading(heading: string): string { + return heading + .toLowerCase() + .replace(/[^a-z0-9\s-]/g, "") + .replace(/\s+/g, "-") + .replace(/-+/g, "-") + .trim(); +} export function generateStaticParams() { return POSTS.map((p) => ({ slug: p.slug })); @@ -30,134 +41,255 @@ export default async function BlogPostPage({ const post = getPost(slug); if (!post) notFound(); + // Extract headings for TOC + const headings = post.sections.filter((s) => s.heading).map((s) => ({ + text: s.heading!, + id: slugifyHeading(s.heading!), + })); + + // Other posts (exclude current) + const otherPosts = POSTS.filter((p) => p.slug !== slug).slice(0, 3); + return (
- {/* Hero */} + {/* Post hero / header */}
-
- - ← All articles - - -
- - {post.category} - - {formatDate(post.date)} - · - {post.readTime} +
+ {/* Breadcrumb */} +
+
-

- {post.title} -

-

{post.excerpt}

+
+
+ + {post.category} + + {formatDate(post.date)} + · + {post.readTime} +
-
- By {post.author} +

+ {post.emoji} {post.title} +

+

{post.excerpt}

+ +
+ By {post.author} +
- {/* Article body */} -
-
- {post.sections.map((section, i) => ( -
- {section.heading && ( -

{section.heading}

- )} + {/* 3-column body */} +
+
- {section.paragraphs?.map((p, j) => ( -

- {p} -

- ))} - - {section.table && ( -
- - - - {section.table.headers.map((h, j) => ( - - ))} - - - - {section.table.rows.map((row, j) => ( - - {row.map((cell, k) => ( - - ))} - - ))} - -
- {h} -
- {cell} -
-
- )} - - {section.list && ( -
    - {section.list.map((item, j) => ( -
  • - - - {item.label && ( - {item.label}: - )} - {item.text} - + {/* ── LEFT SIDEBAR: Table of Contents ── */} +
+ + ) : ( +

No sections

)} - {section.callout && ( -
- {section.callout.emoji} -

{section.callout.text}

-
- )} +
+ + ← All articles + +
- ))} -
+ - {/* Footer CTA */} -
-
-
🌸
-

Try Tia — free during early access

-

- Log feeds, track vaccinations, and build a digital heirloom for your child. Built for Indian families. -

- - Get started → - -
+ {/* ── CENTER: Article body ── */} +
+
+ {post.sections.map((section, i) => ( +
+ {section.heading && ( +

+ {section.heading} +

+ )} + + {section.paragraphs?.map((p, j) => ( +

+ {p} +

+ ))} + + {section.table && ( +
+ + + + {section.table.headers.map((h, j) => ( + + ))} + + + + {section.table.rows.map((row, j) => ( + + {row.map((cell, k) => ( + + ))} + + ))} + +
+ {h} +
+ {cell} +
+
+ )} + + {section.list && ( +
    + {section.list.map((item, j) => ( +
  • + + + {item.label && ( + {item.label}: + )} + {item.text} + +
  • + ))} +
+ )} + + {section.callout && ( +
+ {section.callout.emoji} +

{section.callout.text}

+
+ )} +
+ ))} +
+ + {/* Article footer CTA */} +
+
+
🌸
+

Try Tia — free during early access

+

+ Log feeds, track vaccinations, and build a digital heirloom for your child. Built for Indian families. +

+ + Get started → + +
+ + {/* Back link — visible on mobile too */} +
+ + ← All articles + + + {formatDate(post.date)} · {post.readTime} + +
+
+
+ + {/* ── RIGHT SIDEBAR: More articles + categories ── */} + -
- - ← All articles - - By {post.author} · {formatDate(post.date)} -
diff --git a/src/app/(marketing)/blog/page.tsx b/src/app/(marketing)/blog/page.tsx index 77fc881..6c445a4 100644 --- a/src/app/(marketing)/blog/page.tsx +++ b/src/app/(marketing)/blog/page.tsx @@ -1,6 +1,7 @@ import type { Metadata } from "next"; import Link from "next/link"; import { POSTS, formatDate } from "./posts"; +import { Breadcrumb } from "@/components/marketing/Breadcrumb"; export const metadata: Metadata = { title: "Blog", @@ -8,59 +9,174 @@ export const metadata: Metadata = { "Guides on baby feeding, health milestones, vaccination schedules, and how to make the most of Tia — written for Indian families.", }; +// Derive unique categories + counts from posts +const CATEGORIES = Object.values( + POSTS.reduce>((acc, p) => { + if (!acc[p.category]) { + acc[p.category] = { name: p.category, color: p.categoryColor, count: 0 }; + } + acc[p.category].count++; + return acc; + }, {}) +); + export default function BlogPage() { return (
- {/* Header */} -
-
-
Journal
-

The Tia Blog

-

- Practical guides on baby feeding, health, vaccination schedules, and getting the most out of Tia — written for Indian families. + {/* Breadcrumb */} +

+ +
+ + {/* Page header */} +
+
+
Journal
+

The Tia Blog

+

+ Practical guides on baby feeding, health, vaccination schedules, and getting the most out of Tia — for Indian families.

- {/* Post grid */} -
-
- {POSTS.map((post) => ( -
- -
- {/* Emoji icon */} -
- {post.emoji} -
+ {/* 3-column layout */} +
+
-
- {/* Meta row */} -
- - {post.category} + {/* ── LEFT SIDEBAR: timeline ── */} + + + {/* ── CENTER: post cards ── */} +
+
+ {POSTS.map((post) => ( +
+ +
+ {/* Emoji icon */} +
+ {post.emoji} +
+ +
+ {/* Meta */} +
+ + {post.category} + + {formatDate(post.date)} + · + {post.readTime} +
+ +

+ {post.title} +

+

+ {post.excerpt} +

+ +
+ Read article → +
+
+
+ +
+ ))} +
+
+ + {/* ── RIGHT SIDEBAR: categories + CTA ── */} +
- ))} +
+ + {/* Divider */} +
+ + {/* Quick links */} +
+

Quick reads

+
+ {POSTS.slice(0, 3).map((p) => ( + + {p.emoji} + + {p.title} + + + ))} +
+
+ + {/* Divider */} +
+ + {/* CTA */} +
+
🌸
+

Free early access

+

+ Built for Indian families. No ads, no data selling. +

+ + Get started → + +
+ +
+ +
diff --git a/src/app/(marketing)/layout.tsx b/src/app/(marketing)/layout.tsx index d9b1cc6..16f8928 100644 --- a/src/app/(marketing)/layout.tsx +++ b/src/app/(marketing)/layout.tsx @@ -105,9 +105,10 @@ export default function MarketingLayout({ {/* Bottom bar — different shade */}
-
-

© {new Date().getFullYear()} Tia.  ·  We don't sell your data — we preserve it.

-

Built with ❤️ in India.

+
+

© {new Date().getFullYear()} Tia.

+

We don't sell your data — we preserve it.

+

Built with ❤️ in India.

diff --git a/src/components/marketing/Breadcrumb.tsx b/src/components/marketing/Breadcrumb.tsx new file mode 100644 index 0000000..fb90cd7 --- /dev/null +++ b/src/components/marketing/Breadcrumb.tsx @@ -0,0 +1,32 @@ +import Link from "next/link"; + +export interface BreadcrumbItem { + label: string; + href?: string; +} + +export function Breadcrumb({ items }: { items: BreadcrumbItem[] }) { + return ( + + ); +}