Next.js Discord

Discord Forum

Best way to set titles in app router with lots of pages?

Answered
Sun bear posted this in #help-forum
Open in Discord
Avatar
Sun bearOP
Like <domain> | <page>
example.com | login for example.
Answered by B33fb0n3
that depends on how you structure your project. Some examples on how you can structure your project are here: https://nextjs.org/docs/app/building-your-application/routing/colocation#project-organization-strategies

I guess minimum one of the suites your case
View full answer

28 Replies

Avatar
@Sun bear Like `<domain> | <page>` `example.com | login` for example.
Avatar
you can use a template inside your title or description or ... to put everything together. Example:
export const metadata: Metadata = {
    title: {
        default: "I am some title", // this will be used as title on the page where you add this metadata
        template: "%s | Example.com", // the %s will be exchanged with the new title, when you set a new title someone on any child
    },
}
Avatar
@Sun bear How would I do it from the page file where its marked as 'use client'?
Avatar
you can only set the metadata inside server component. However you can do a little trick and set the document.title to your desired title
Avatar
@Sun bear is there any better ways?
Avatar
what's your use case? What do you want to do?
Avatar
@B33fb0n3 what's your use case? What do you want to do?
Avatar
Sun bearOP
Literally just add custom titles to indicate what page the user is one, but alot of my pages are marked as 'use client' due to the states and everything involved
Avatar
@Sun bear Literally just add custom titles to indicate what page the user is one, but alot of my pages are marked as 'use client' due to the states and everything involved
Avatar
the page.tsx itself is by default always a server component in app router. So keep this serverside especially for that kind of stuff and only import your client components into it. Like that most of your page will be rendered serverside and only the parts that need to be client components are client components
Avatar
@Sun bear what file structure should I use for this then?
Avatar
you would use a page.tsx as server component and inside this you would import your client components. It could look like this:
// page.tsx

// add some metadata

export default function Page() {
  // serverside
  const post = await getLastBlockPost()

  return <>
  <h1>My Blog Page</h1>
  <BlogPost post={post}/> // serverside
  <CommentSection initialComments={post.comments} postId={post.id}/> // clientside
</>
}
Avatar
@Sun bear I understand that part, I'm asking how I would structure the actual files in my project directory
Avatar
create a page.tsx and create a YourClientComponent.tsx as your client component file. Nothing more is needed for what I am talking about
Avatar
@Sun bear in the same folder?
Avatar
that depends on how you structure your project. Some examples on how you can structure your project are here: https://nextjs.org/docs/app/building-your-application/routing/colocation#project-organization-strategies

I guess minimum one of the suites your case
Answer
Avatar
@Sun bear in the same folder?
Avatar
Indian oil sardine
i'm using something like this

app/
├── (routes)
│   └── example-page/
│       ├── page.tsx
│       └── page.client.tsx

page.tsx is the server component where i set metadata

import type { Metadata } from "next";
import { getUser } from "@/_data/user";
import { getEmployeeDirectory } from "./_lib/employee-directory.queries";
import {
  dehydrate,
  HydrationBoundary,
  QueryClient,
} from "@tanstack/react-query";
import EmployeeDirectoryClient from "./page.client";

export const metadata: Metadata = {
  title: "Employee Directory | Your Site",
};

export default async function EmployeeDirectoryPage() {
  const user = await getUser();

  const queryClient = new QueryClient();
  await queryClient.prefetchQuery({
    queryKey: ["employees"],
    queryFn: () => getEmployeeDirectory(),
  });

  return (
    <HydrationBoundary state={dehydrate(queryClient)}>
      <EmployeeDirectoryClient user={user} />
    </HydrationBoundary>
  );
}


page.client.tsx is the client component

"use client";

import { Suspense } from "react";
import { Heading } from "@/components/catalyst/heading";
import { DataTable } from "@/components/data-table/data-table";
import { columns } from "./columns";
import { useQuery } from "@tanstack/react-query";
import { getEmployeeDirectory } from "./_lib/employee-directory.queries";
import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton";
import { UpdateEmployeeDirectory } from "./_components/update-employee-directory";

export default function EmployeeDirectoryClient({ user }: { user: User }) {
    const { data: employees } = useQuery({
      queryKey: ["employees"],
      queryFn: () => getEmployeeDirectory(),
    });
  return (
    <div>
      <div>
        <Heading>Employee Directory</Heading>
      </div>
      <Suspense fallback={<DataTableSkeleton />}>
         <DataTable
            data={employees}
            columns={columns}
          />
      </Suspense>
    </div>
  );
}
Image
Avatar
@Sun bear solved?
Avatar
@B33fb0n3 <@1080311571324084275> solved?
Avatar
Sun bearOP
Not yet, my data is fetched from a seperate Express backend and I'm unsure how I would do it with that?
Avatar
@Sun bear Not yet, my data is fetched from a seperate Express backend and I'm unsure how I would do it with that?
Avatar
you can either fetch it inside your page.tsx and set it thought the generateMetadata function or fetch your express app clientside and set it via document.title both ways are technically possible
Avatar
@Sun bear Does `generateMetadata` work in a client component?
Avatar
no, it's also only for server components. You can also do a combination: fetch your epxress server, serverside and pass it down via props and set the title to the value from the props
Avatar
@B33fb0n3 no, it's also only for server components. You can also do a combination: fetch your epxress server, serverside and pass it down via props and set the title to the value from the props
Avatar
Sun bearOP
Okay, say I want to fetch data in one page, and reuse that response across all my other components, and I need the request to be made in the client, how would I go about doing this when switching to SSR
If that makes sense
Avatar
@Sun bear Okay, say I want to fetch data in one page, and reuse that response across all my other components, and I need the request to be made in the client, how would I go about doing this when switching to SSR
Avatar
What you are saying makes no sense:

you saying that you want to fetch it on the client
request to be made in the client
But on the other hand you want to use SSR (Serverside rendered)
switching to SSR

The best flow would be to fetch everything serverside and pass the data to your components that needs them. Like that you can use SSR and also get rid of all the other problems of setting metadata, titles, …
Avatar
@B33fb0n3 What you are saying makes no sense: you saying that you want to fetch it on the client > request to be made in the client But on the other hand you want to use SSR (**Server**side rendered) > switching to SSR The best flow would be to fetch everything serverside and pass the data to your components that needs them. Like that you can use SSR and also get rid of all the other problems of setting metadata, titles, …
Avatar
Sun bearOP
Nevermind on that, got it mostly sorted out. One question though, I've noticed that when switching to private folders (like done in the images you sent above) for better organisation, I get the following error when trying to render any icons, I'll attach the error & next config below
/** @type {import('next').NextConfig} */
const nextConfig = {
    webpack(config) {
        config.module.rules.push({
            test: /\.svg$/i,
            issuer: /\.[jt]sx?$/,
            use: ['@svgr/webpack'],
        });

        return config;
    },
};

export default nextConfig;
Image
Avatar
@B33fb0n3 Which message solved the initial question of this thread?
Avatar
Sun bearOP
Sorting using private folders basically
But also raised new issues I need help fixing
Avatar
@Sun bear But also raised new issues I need help fixing
Avatar
your new topic looks like a whole different topic. Please create another thread to be able to find solutions. If I marked the wrong message as solution, feel free to mark another one