From f51d3703ab8756eb666228c8f99ea020de66255d Mon Sep 17 00:00:00 2001 From: Josephat-S Date: Tue, 26 May 2026 10:03:19 +0200 Subject: [PATCH] implement full blog design with article pages --- .../app/articles/[slug]/page.tsx | 310 ++++++++++++++++++ .../blog/nextjs-monolith/app/globals.css | 48 +++ .../nextjs-monolith/components/AuthorCard.tsx | 43 +++ .../components/ShareButtons.tsx | 43 +++ .../components/TableOfContents.tsx | 37 +++ 5 files changed, 481 insertions(+) create mode 100644 templates/blog/nextjs-monolith/app/articles/[slug]/page.tsx create mode 100644 templates/blog/nextjs-monolith/components/AuthorCard.tsx create mode 100644 templates/blog/nextjs-monolith/components/ShareButtons.tsx create mode 100644 templates/blog/nextjs-monolith/components/TableOfContents.tsx diff --git a/templates/blog/nextjs-monolith/app/articles/[slug]/page.tsx b/templates/blog/nextjs-monolith/app/articles/[slug]/page.tsx new file mode 100644 index 0000000..59662a8 --- /dev/null +++ b/templates/blog/nextjs-monolith/app/articles/[slug]/page.tsx @@ -0,0 +1,310 @@ +import Link from 'next/link'; +import TableOfContents from '../../../components/TableOfContents'; +import AuthorCard from '../../../components/AuthorCard'; +import ShareButtons from '../../../components/ShareButtons'; + +interface ArticlePageProps { + params: { slug: string }; +} + +export default function ArticlePage({ params }: ArticlePageProps) { + const title = params.slug + .split('-') + .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) + .join(' '); + + const headings = [ + { id: 'getting-started', text: 'Getting Started', level: 2 }, + { id: 'key-concepts', text: 'Key Concepts', level: 2 }, + { id: 'implementation', text: 'Implementation', level: 2 }, + { id: 'best-practices', text: 'Best Practices', level: 2 }, + { id: 'conclusion', text: 'Conclusion', level: 2 }, + ]; + + const relatedArticles = [ + { + slug: 'tailwind-css-best-practices', + title: 'Tailwind CSS Best Practices for Large Projects', + excerpt: 'Discover patterns and strategies for maintaining clean Tailwind CSS in enterprise applications.', + author: 'Alex Chen', + date: 'Jun 12, 2024', + category: 'CSS', + }, + { + slug: 'typescript-generics-explained', + title: 'TypeScript Generics Explained Simply', + excerpt: 'A practical guide to understanding and using TypeScript generics in your everyday code.', + author: 'Maria Garcia', + date: 'Jun 10, 2024', + category: 'TypeScript', + }, + { + slug: 'react-server-components', + title: 'Understanding React Server Components', + excerpt: 'Deep dive into how React Server Components work and when to use them.', + author: 'David Park', + date: 'Jun 8, 2024', + category: 'React', + }, + ]; + + return ( +
+
+
+ {/* Main Content */} +
+ {/* Article Header */} +
+ + Tutorial + +

+ {title} +

+
+ Jane Smith + · + Jun 15, 2024 + · + 8 min read +
+ {/* Featured Image Placeholder */} +
+ Featured Image +
+
+ + {/* Article Body */} +
+

+ Building modern web applications requires a solid understanding of the tools and + frameworks available today. In this comprehensive guide, we will explore the key + concepts, patterns, and best practices that will help you build production-ready + applications with confidence. +

+ +

+ Getting Started +

+

+ Before diving into the implementation details, let's set up our development + environment and understand the project structure. The foundation of any great + application starts with a well-organized codebase and clear conventions that + your team can follow consistently. +

+

+ We'll be using Next.js 14 with the App Router, which provides a powerful + file-system based routing mechanism, built-in optimizations, and first-class + support for React Server Components. This combination gives us the best of both + worlds: excellent developer experience and outstanding performance. +

+ + {/* Code Block */} +
+                {`// app/layout.tsx
+import type { Metadata } from 'next';
+import './globals.css';
+
+export const metadata: Metadata = {
+  title: 'My Application',
+  description: 'Built with Next.js 14',
+};
+
+export default function RootLayout({
+  children,
+}: {
+  children: React.ReactNode;
+}) {
+  return (
+    
+      {children}
+    
+  );
+}`}
+              
+ +

+ Key Concepts +

+

+ Understanding the core concepts is essential before moving to implementation. + These principles will guide your architectural decisions and help you write + maintainable, scalable code that stands the test of time. +

+
    +
  • + Server Components — Render on the server by default, reducing + client-side JavaScript and improving initial page load performance. +
  • +
  • + Streaming — Progressively render UI from the server, showing + content as it becomes available without blocking the entire page. +
  • +
  • + Data Fetching — Fetch data directly in components using async/await, + with automatic request deduplication and caching built in. +
  • +
  • + Route Handlers — Build API endpoints using the Web Request and + Response APIs with full TypeScript support. +
  • +
+ +
+ “The best code is the code that doesn't need to exist on the client. + Server Components let us move complexity to where it belongs — the server.” + + — React Core Team + +
+ +

+ Implementation +

+

+ Now that we understand the fundamentals, let's build a real component that + demonstrates these concepts in action. We'll create a data-fetching component + that leverages Server Components for optimal performance while maintaining a + clean, reusable API. +

+ + {/* Code Block */} +
+                {`// components/ArticleList.tsx
+interface Article {
+  id: string;
+  title: string;
+  excerpt: string;
+  publishedAt: string;
+}
+
+async function getArticles(): Promise {
+  const res = await fetch('https://api.example.com/articles', {
+    next: { revalidate: 3600 },
+  });
+  return res.json();
+}
+
+export default async function ArticleList() {
+  const articles = await getArticles();
+
+  return (
+    
+ {articles.map((article) => ( +
+

{article.title}

+

{article.excerpt}

+ +
+ ))} +
+ ); +}`}
+
+ +

+ Best Practices +

+
    +
  1. + Keep components focused — Each component should have a single + responsibility. Split large components into smaller, composable pieces. +
  2. +
  3. + Use TypeScript strictly — Enable strict mode and define proper + interfaces for all props, API responses, and shared types. +
  4. +
  5. + Optimize data fetching — Colocate data fetching with the + components that need it, and use proper caching strategies. +
  6. +
  7. + Handle errors gracefully — Implement error boundaries and + loading states to provide a smooth user experience. +
  8. +
  9. + Write tests early — Test critical paths and edge cases from + the start. Use integration tests for data flows and unit tests for utilities. +
  10. +
+ +

+ Conclusion +

+

+ Building modern web applications is an evolving discipline, but the fundamentals + remain constant: write clean code, think about your users, and leverage the + platform. With the tools and patterns we've covered in this guide, you're + well-equipped to build applications that are fast, accessible, and maintainable. + Keep experimenting, keep learning, and most importantly — keep shipping. +

+
+ + {/* Share Buttons */} + + + {/* Author Card */} + + + {/* Related Articles */} +
+

Related Articles

+
+ {relatedArticles.map((article) => ( + + + {article.category} + +

+ {article.title} +

+

+ {article.excerpt} +

+
+ {article.author} + · + {article.date} +
+ + ))} +
+
+
+ + {/* Table of Contents Sidebar */} + +
+
+
+ ); +} diff --git a/templates/blog/nextjs-monolith/app/globals.css b/templates/blog/nextjs-monolith/app/globals.css index 283fef5..96b135b 100644 --- a/templates/blog/nextjs-monolith/app/globals.css +++ b/templates/blog/nextjs-monolith/app/globals.css @@ -57,3 +57,51 @@ body { color: var(--text-color); font-family: var(--font-family); } + +/* ===== Article Typography ===== */ +.article-content h2 { + scroll-margin-top: 5rem; +} + +.article-content pre { + background-color: var(--bg-secondary); + border: 1px solid var(--border-color); + border-radius: var(--radius); + padding: 1rem 1.25rem; + overflow-x: auto; + margin-bottom: 1.5rem; + font-size: 0.875rem; + line-height: 1.7; +} + +.article-content code { + font-family: 'JetBrains Mono', 'Fira Code', ui-monospace, monospace; +} + +.article-content blockquote { + border-left: 4px solid var(--primary); + padding-left: 1rem; + font-style: italic; + color: var(--text-secondary); + margin: 1.5rem 0; +} + +.article-content ul, +.article-content ol { + margin-left: 1.5rem; + margin-bottom: 1.5rem; +} + +.article-content ul { + list-style-type: disc; +} + +.article-content ol { + list-style-type: decimal; +} + +.article-content li { + margin-bottom: 0.5rem; + color: var(--text-color); + line-height: 1.7; +} diff --git a/templates/blog/nextjs-monolith/components/AuthorCard.tsx b/templates/blog/nextjs-monolith/components/AuthorCard.tsx new file mode 100644 index 0000000..e876c93 --- /dev/null +++ b/templates/blog/nextjs-monolith/components/AuthorCard.tsx @@ -0,0 +1,43 @@ +interface AuthorCardProps { + name: string; + role: string; + bio: string; + avatar: string; +} + +export default function AuthorCard({ name, role, bio, avatar }: AuthorCardProps) { + return ( +
+
+
+ {avatar} +
+
+

{name}

+

{role}

+

{bio}

+
+ {/* GitHub */} + + + + {/* Twitter */} + + + + {/* Website */} + + + +
+
+
+
+ ); +} diff --git a/templates/blog/nextjs-monolith/components/ShareButtons.tsx b/templates/blog/nextjs-monolith/components/ShareButtons.tsx new file mode 100644 index 0000000..05db327 --- /dev/null +++ b/templates/blog/nextjs-monolith/components/ShareButtons.tsx @@ -0,0 +1,43 @@ +interface ShareButtonsProps { + title: string; + slug: string; +} + +export default function ShareButtons({ title, slug }: ShareButtonsProps) { + return ( +
+

Share this article

+
+ {/* Twitter/X */} + + + Twitter + + {/* LinkedIn */} + + + LinkedIn + + {/* Copy Link */} + +
+
+ ); +} diff --git a/templates/blog/nextjs-monolith/components/TableOfContents.tsx b/templates/blog/nextjs-monolith/components/TableOfContents.tsx new file mode 100644 index 0000000..3597a85 --- /dev/null +++ b/templates/blog/nextjs-monolith/components/TableOfContents.tsx @@ -0,0 +1,37 @@ +interface Heading { + id: string; + text: string; + level: number; +} + +interface TableOfContentsProps { + headings: Heading[]; +} + +export default function TableOfContents({ headings }: TableOfContentsProps) { + return ( + + ); +}