reactjsnext.jsserver-side-renderingnext.js13static-site-generation

dynamic routing and metadata generation in nextjs app router


I'm building a blog site in nextjs with app router. I'm stuck with static site generation. I tried reading this official doc of nextjs but wasn't able to grasp it .... please help me out. here is my project structure. folder structure I have a file where I'm storing blog's data i.e, blogData.js

import { FullStackDeveloper, GraphicDesigner } from "@/assets/team";
    
    const BlogData = [
      {
        id: 0,
        title: "Exploring the Power of React.js for Interactive Web Applications",
        cover: FullStackDeveloper,
        desc: "Delve into the incredible capabilities of React.js for creating dynamic and interactive web applications. Discover how React.js enhances user experience, improves performance, and enables seamless data management. Gain insights into the benefits and best practices of using React.js for your next web development project.",
        keywords: [
          "React.js",
          "interactive web applications",
          "user experience",
          "performance",
          "data management",
          "web development",
          "best practices",
        ],
        date: "23rd Jun 2023",
        url: "exploring-the-power-of-react-js-for-interactive-web-applications",
      },
      {
        id: 1,
        title: "Mastering the Art of Design: Unleashing Creativity and Aesthetics",
        cover: GraphicDesigner,
        desc: "Explore the world of design and discover strategies to unlock your creativity. Learn about the principles of effective design, color theory, typography, and user-centered design. Unleash your artistic potential and create visually stunning experiences.",
        keywords: [
          "design",
          "creativity",
          "aesthetics",
          "color theory",
          "typography",
          "user-centered design",
          "visual experience",
        ],
        data: "25th Jun 2023",
        url: "mastering-the-art-of-design-unleashing-creativity-and-aesthetics",
      },
    ];
    
    export { BlogData };

here is layout.js

export const metadata = {
  title: "dynamic blogs",
  description: "dynamic descriptions",
};
export default function layodut({ children }) {
  return (
    <>
      {children}
    </>
  );
}

here is my page.js for blog

export default function page({ params }) {
  return (
    <>
      <div className="overflow-hidden bg-white text-black md:py-20">
        <div className="container relative mx-auto px-4">
          <div className="grid grid-cols-1 items-center px-4 py-20 xl:py-10">
            <div>
              <h1 className="relative z-10 text-center text-6xl font-bold xl:text-9xl">
                Welcome to
                <br />
                Our Blog
              </h1>
              <span className="absolute top-0 w-full transform whitespace-nowrap text-center text-[250px] font-extrabold text-gray-400 opacity-30 blur-[1px] ">
                BLOGS
              </span>
              <p className="mx-auto mt-10 text-center text-base xl:w-2/3 xl:text-2xl">
                Explore a wide range of topics on our blog, covering web
                development, design, digital marketing, and technology. Stay
                updated with industry trends, practical tips, and expert
                insights. Discover the latest techniques and technologies in web
                development, get inspired by design trends, learn digital
                marketing strategies, and stay informed about emerging
                technologies. Join our community and empower yourself with
                knowledge and inspiration.
              </p>
            </div>
          </div>
          {/* <h1>id : {}</h1> */}
          <h1>Title : {params.desc}</h1>
        </div>
      </div>
    </>
  );
}

how can I get the site to generate a title and description for based on the url from blogData.js. I did tried those generateStaticParams function from nextjs official docs but weren't able to achieve the desired the result.


Solution

  • In this case, I suggest you to use generateMetaData for your each blog page.

    Anyway, you can define the metadata statically like that for two pages - /blogs and /blogs/***.

    /app/blogs/layout.js

    import { Metadata } from 'next';
    import * as React from 'react';
    export const metadata = {
      title: {
        default: 'dynamic blogs',
        template: `%s - Blog`,
      },
      description: 'dynamic description'
    }
    ....
    

    /app/blogs/[blogTitle]/layout.js

    import { Metadata } from 'next';
    import * as React from 'react';
    export const metadata = {
      title: 'Content',
      description: 'Blog Description'
    }
    .... 
    

    then the title will be 'Content - Blog' for '/blogs/****' routes.

    You should define metadata in layout.js files, not page.js. In documentation, I have read that both cases are available, but on my side, only one side(layout) is working.

    And regarding the code style, I would like to suggest some opinions. This file structure would be better for your blog website.

    enter image description here

    and then should update the layout.js like that /app/blogs/[id]/layout.js

    import { Metadata } from 'next';
    import * as React from 'react';
    import { BlogData } from '../../blogData.js';     // should update this path
    
    export async function generateMetadata({ params }, parent) {
      const id = params.id;
    
      const blog = BlogData.find(item => item.id === id);
    
      return {
        title: blog.title,
        description: blog.description,
        keywords: blog.keywords
      };
    }
    ....
    

    I hope this helps you.