DEV Community

Ramu Narasinga
Ramu Narasinga

Posted on • Edited 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 me:

Hey, my name is Ramu Narasinga. I study large open-source projects and create content about their codebase architecture and best practices, sharing it through articles, videos.

I am open to work on an interesting project. Send me an email at ramu.narasinga@gmail.com

My Github - https://github.com/ramu-narasinga
My website - https://ramunarasinga.com
My Youtube channel - https://www.youtube.com/@thinkthroo
Learning platform - https://thinkthroo.com
Codebase Architecture - https://app.thinkthroo.com/architecture
Best practices - https://app.thinkthroo.com/best-practices
Production-grade projects - https://app.thinkthroo.com/production-grade-projects

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)