Next.js Discord

Discord Forum

Am I using generateStaticParams the wrong way?

Answered
English Angora posted this in #help-forum
Open in Discord
English AngoraOP
So I have a server component/page: /projects/[slug]/page.tsx
which is a single page for a specific project. I know this should be a client component but since this is for my portfolio website, it's fine this way.

I have all of my project details with this file structure:

- public
- warehouse
- projects
- project-name-1 and so on..

And my code for [slug]/page.tsx looks like:

To fetch all of my project titles
function getAllDirectFolderNames(path: string) {
  return fs
    .readdirSync(path, { withFileTypes: true })
    .filter((dirent) => dirent.isDirectory())
    .map((dirent) => dirent.name);
}

export async function generateStaticParams() {
  const projectTitles = getAllDirectFolderNames(
    withPublic(WAREHOUSE.ProjectDir, '')
  );
  const params = projectTitles.map((title) => ({
    params: {
      slug: title,
    },
  }));
  return params;
}


For project details fetching
const getProject = cache(async (slug: string): Promise<IProject | null> => {
  // fs reading fom project[slug]'s index.json, doing stuffs and returning the project
  return project;
});

UI to be rendered
export default async function Project({
  params: { slug },
}: {
  params: { slug: string };
}) {
  const projectTitle = decodeURI(slug);
  const project = await getProject(projectTitle);

// blah blah


It successfully builds,
npm run start
running build locally, everything works fine.
Eg.
http://localhost:3000/projects/my-project

but,

It throws an error
Internal Server Error 500
on production.
Eg.
https://example.com/projects/my-project


So, my question is, am I trying to achieve something that's not possible or I'm doing it wrong way (if so guide me how do I do it the right way).

Thanks in advance.
Answered by joulev
It should be { slug: title } instead of { params: { slug: title } }
View full answer

11 Replies

@English Angora So I have a server component/page: **/projects/[slug]/page.tsx** which is a single page for a specific project. I know this should be a client component but since this is for my portfolio website, it's fine this way. I have all of my project details with this file structure: - public - warehouse - projects - project-name-1 and so on.. And my code for [slug]/page.tsx looks like: **To fetch all of my project titles** function getAllDirectFolderNames(path: string) { return fs .readdirSync(path, { withFileTypes: true }) .filter((dirent) => dirent.isDirectory()) .map((dirent) => dirent.name); } export async function generateStaticParams() { const projectTitles = getAllDirectFolderNames( withPublic(WAREHOUSE.ProjectDir, '') ); const params = projectTitles.map((title) => ({ params: { slug: title, }, })); return params; } **For project details fetching** const getProject = cache(async (slug: string): Promise<IProject | null> => { // fs reading fom project[slug]'s index.json, doing stuffs and returning the project return project; }); **UI to be rendered** export default async function Project({ params: { slug }, }: { params: { slug: string }; }) { const projectTitle = decodeURI(slug); const project = await getProject(projectTitle); // blah blah It successfully builds, npm run start running build locally, everything works fine. Eg. http://localhost:3000/projects/my-project but, It throws an error Internal Server Error 500 on production. Eg. https://example.com/projects/my-project So, my question is, am I trying to achieve something that's not possible or I'm doing it wrong way (if so guide me how do I do it the right way). Thanks in advance.
It should be { slug: title } instead of { params: { slug: title } }
Answer
That said, why don’t you use a js constant or a json file to hold the data? You shouldn’t need to use the public folder or fs here
Also you might want to use export const dynamicParams = false as well https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamicparams
@joulev That said, why don’t you use a js constant or a json file to hold the data? You shouldn’t need to use the public folder or fs here
English AngoraOP
I have all of my projects data on index.json of inside their respective dirs on public folder, how should I have done this following a good practice?
@English Angora I have all of my projects data on index.json of inside their respective dirs on public folder, how should I have done this following a good practice?
You can simply import the json file directly. In TypeScript it is as simple as

import data from "./data.json"

The json file can be anywhere, no need to be in the public folder.
English AngoraOP
I forgot to mention that i'm actually using fetch to get that json content, but I guess I still need fs as I'm using it to get the image buffer and generate placeholder image using plaiceholder package
And also how would you use
import data from "./data.json"
inside a function?
@English Angora And also how would you use import data from "./data.json" inside a function?
data should already be a js object containing the content of the json file. So you just use that object directly. No “fetching” functions needed
English AngoraOP
Right, I should've done that. I did had a confusion whether to use json or js object for storing data but chatgpt gaslighted me into doing this lol, gotta change things now, thanks..
@joulev It should be { slug: title } instead of { params: { slug: title } }
This worked right? The data fetching part is just a comment from me, it is not absolutely necessary to avoid 500’s