DEV Community

Ramu Narasinga
Ramu Narasinga

Posted on

A comparison of metadata configurations between Lobechat and Shadcn/ui

In this article, you will learn how metadata is configured in Lobechat and Shadcn/ui. This comparison shows two ways to configure your metadata, key difference here is that Shadcn/ui is a UI components provider. You don’t see any API calls made to the backend and you don’t find any database involved either. Lobechat, on the other hand, is our team’s favorite and is quite complex and a large project that has a database, uses tRPC to make API calls.

You will find out how the files and folders are used to configure metadata depending on the context, more on this in the later parts of this article.

There are two ways you can define metadata in a Next.js layout or a page

  1. Config-based Metadata: Export a static metadata object or a dynamic generateMetadata function in a layout.js or page.js file.

  2. File-based Metadata: Add static or dynamically generated special files to route segments.

Read more about:

- Static metadata

- Dynamic metadata

- File Based Metadata

With this information from the documentation, we will find out which way Shadcn/ui and Lobechat have chosen.

Image description

Shadcn/ui metadata configuration

In the www/app/layout.tsx in Shadcn/ui source code, metadata is defined as shown below:

export const metadata: Metadata = {
  title: {
    default: siteConfig.name,
    template: `%s - ${siteConfig.name}`,
  },
  metadataBase: new URL(siteConfig.url),
  description: siteConfig.description,
  keywords: [
    "Next.js",
    "React",
    "Tailwind CSS",
    "Server Components",
    "Radix UI",
  ],
  authors: [
    {
      name: "shadcn",
      url: "https://shadcn.com",
    },
  ],
  creator: "shadcn",
  openGraph: {
    type: "website",
    locale: "en_US",
    url: siteConfig.url,
    title: siteConfig.name,
    description: siteConfig.description,
    siteName: siteConfig.name,
    images: [
      {
        url: siteConfig.ogImage,
        width: 1200,
        height: 630,
        alt: siteConfig.name,
      },
    ],
  },
  twitter: {
    card: "summary_large_image",
    title: siteConfig.name,
    description: siteConfig.description,
    images: [siteConfig.ogImage],
    creator: "@shadcn",
  },
  icons: {
    icon: "/favicon.ico",
    shortcut: "/favicon-16x16.png",
    apple: "/apple-touch-icon.png",
  },
  manifest: `${siteConfig.url}/site.webmanifest`,
}
Enter fullscreen mode Exit fullscreen mode

What this means is that Shadcn/ui uses static metadata. SiteConfig is imported as shown below:

import { META_THEME_COLORS, siteConfig } from "@/config/site"
Enter fullscreen mode Exit fullscreen mode

Lobechat metadata configuration

In the Lobechat/src/app/layout.tsx, you will find the below code:

export { generateMetadata } from './metadata';
Enter fullscreen mode Exit fullscreen mode

Image description

generateMetadata here means that Lobechat uses dynamic metadata. Below is the code picked from Lobechat metadata file.

import { Metadata } from 'next';

import { appEnv } from '@/config/app';
import { BRANDING_LOGO_URL, BRANDING_NAME, ORG_NAME } from '@/const/branding';
import { OFFICIAL_URL, OG_URL } from '@/const/url';
import { isCustomBranding, isCustomORG } from '@/const/version';
import { translation } from '@/server/translation';

const BASE_PATH = appEnv.NEXT_PUBLIC_BASE_PATH;

// if there is a base path, then we don't need the manifest
const noManifest = !!BASE_PATH;

export const generateMetadata = async (): Promise<Metadata> => {
  const { t } = await translation('metadata');

  return {
    alternates: {
      canonical: OFFICIAL_URL,
    },
    appleWebApp: {
      statusBarStyle: 'black-translucent',
      title: BRANDING_NAME,
    },
    description: t('chat.description', { appName: BRANDING_NAME }),
    icons: isCustomBranding
      ? BRANDING_LOGO_URL
      : {
          apple: '/apple-touch-icon.png?v=1',
          icon: '/favicon.ico?v=1',
          shortcut: '/favicon-32x32.ico?v=1',
        },
    manifest: noManifest ? undefined : '/manifest.json',
    metadataBase: new URL(OFFICIAL_URL),
    openGraph: {
      description: t('chat.description', { appName: BRANDING_NAME }),
      images: [
        {
          alt: t('chat.title', { appName: BRANDING_NAME }),
          height: 640,
          url: OG_URL,
          width: 1200,
        },
      ],
      locale: 'en-US',
      siteName: BRANDING_NAME,
      title: BRANDING_NAME,
      type: 'website',
      url: OFFICIAL_URL,
    },
    title: {
      default: t('chat.title', { appName: BRANDING_NAME }),
      template: `%s · ${BRANDING_NAME}`,
    },
    twitter: {
      card: 'summary_large_image',
      description: t('chat.description', { appName: BRANDING_NAME }),
      images: [OG_URL],
      site: isCustomORG ? `@${ORG_NAME}` : '@lobehub',
      title: t('chat.title', { appName: BRANDING_NAME }),
    },
  };
};
Enter fullscreen mode Exit fullscreen mode

In the Shadcn/ui siteconfig, we saw it contains brand information and relevant urls, but Lobechat has done it differently. There’s a const folder containing files such as

This configuration in the Lobechat comes from a folder named const instead of config, like in Shadcn/ui, because config folder in Lobechat

About us:

At Thinkthroo, we study large open source projects and provide architectural guides. We have developed reusable Components, built with tailwind, that you can use in your project. We offer Next.js, React and Node development services.

Book a meeting with us to discuss your project.

Image description

References:

1. https://github.com/lobehub/lobe-chat/blob/main/src/app/metadata.ts

2. https://github.com/shadcn-ui/ui/blob/main/apps/www/config/site.ts

3. https://nextjs.org/docs/app/building-your-application/optimizing/metadata#static-metadata

4. https://github.com/lobehub/lobe-chat/blob/main/src/app/layout.tsx#L47

5. https://nextjs.org/docs/app/building-your-application/optimizing/metadata#dynamic-metadata

Top comments (0)