So let's now fetch our actual post data
for this single post here.
Now, the cool thing is that,
in the lib folder, in the posts-util file,
we already got this get post data function,
and we can basically utilize this.
The only problem we'll have is
that it expects a file name.
It expects a file name,
and, when we load, a single post here,
we'll only have to slug.
Which is the file name,
without the file extension.
So we either, convert this,
slug to a file name,
by adding an extension here,
when reaching out to, get post data,
or we make, get post data more flexible.
We could, for example named this, post identifier,
to make it a bit more generic,
then, we create the post slug,
right away, as a first step,
by taking our post identifier,
and replacing the extension.
And if it doesn't have
that extension, that's no problem.
So if we received just this slug,
replace will just do nothing,
which is all defined.
And then here when we need the file path,
we don't just pass in the post identifier,
but instead, we create a string
with a template literal,
and we use post slug,
which is guaranteed to not have an extension,
and add.md here.
So we always create a file, path
or a file name with extension here.
And if we restructure our code like this,
it should already work.
Now we can call, get post data,
with a file name, with an extension,
or with just a slug.
Therefore now we can export this,
to then use it,
in our single post page.
Because here, I wanna get a single post,
for a given slug.
Now for that, here in post detailed page,
I'll again export, a function,
to get static props function.
Again for the same reasons
as mentioned before,
get (indistinct) I props could be used here,
but isn't better.
And then here we get this, context object.
We get this in all get static props functions,
but we haven't needed it before.
Now we do need it,
because we can get our params, out of context.
That's what you also learned in the course.
Context has a params key,
and that's simply, is, then an object,
with the, concrete values,
of all the dynamic segments
that might lead to this file.
So in this case,
we'll be able to,
extract the concrete slug value, from params.
Because we have that dynamic segment,
in this file name.
So here we then have to, slug,
which we get from params.
And now we can use that slug
to get the data for a single post,
with get post data,
so importing that function
from the lib folder into posts-util file,
and passing the slug as our argument.
That will then give us the data, for that file,
it will read that data for that file,
and it's able to read that because,
get static props executes during the build process,
or on the server, not in the client.
And then therefore we get our, post data here.
And hence we can then return our object,
as we always have,
where we set the props for our component.
And here we can add the post prop,
which holds that post data.
And here we could make a case
for adding revalidate.
Here, we're not going through all the posts.
We're fetching the data for a single post.
So this will be very fast.
And if we set revalidate to let's say 600 here,
then we ensure,
that if we ever updated a markdown file,
without rebuilding the entire application,
that then still,
we do get that latest data,
at least once every 10 minutes.
So that we don't have
to rebuild the entire application,
just because we fixed a typo
in one of our markdown files.
We could do this here, because here,
rebuilding after deployment,
will be much faster than if we do it
for the other pages,
where we have to go through all the post files,
which takes a bit longer.
And therefor would slow down,
some of the requests.
Here, it would not slow down the requests at all,
or not by much at least.
And we only do it once every 10 minutes anyways.
Of course you can tweak this duration
to a duration that fits your needs though.
You can make it longer or shorter.
But with that, we now have get static props here.
However, since this is a dynamic page,
you'll learn that get static props can't work on its own.
We need to pair it,
with get static paths,
to let Next know,
which concrete slug values it should pre-generate.
And therefore we need
to export another function here.
We need to export the get static paths function.
This returns an object,
with all the paths that should be prepared.
So with all the concrete values
for a slug that should be prepared.
And that's an array full of objects,
where we set params,
to another nested object,
and then provide our concrete slug values.
That's what you learned.
Now we can, not prepare anything,
and basically just set paths
to an empty array,
and set fallback to true.
Then the data will be prepared
and fetched on the mound,
when we visit this page.
With fallback true,
we should also render some,
fallback content though,
for this scenario that the post hasn't been loaded yet.
Or we set fall back to blocking,
to wait until it has been generated.
This could be fine.
And it could be fine if you have a blog
with, thousands of posts,
where a lot of those posts are,
rarely read and rarely visited,
and you don't wanna pre-generate all those posts.
Then, using a pattern like this could make sense.
Or you pre-generate some of your posts,
your most popular posts,
and not all of them.
In this blog here,
where we will only have a couple of posts,
only a couple of dozens,
or hundreds of posts,
pre-rendering all posts, isn't too difficult
and isn't too much work.
And hence I'll set fall back to false,
and explicitly define all paths in advance.
And for defining all paths in advance,
I need to know, which paths we have.
Now we can get all those paths
by using another function
from the posts-util folder.
They're in get all posts.
We get all our post files.
Then we all to read all the data from there.
Now that's a bit overkill here.
I'm not interested in all the data here.
I'm just interested in getting the post files in this case.
Hence, I will actually refactor this,
and put this here, this code,
where I read all the files
from the posts directory,
into a separate function,
maybe here at the very top,
which I'll name get posts files,
and they are all returned fs readdir sync,
and I'll export this function,
so that we can also use it outside of this file.
And then down there and get all posts.
I'll now call, get posts files,
so that this works again.
So that allows me to just get all the post file names,
without doing all the sorting and mapping,
which will slow down the process a bit,
which is just not needed,
for pre-rendering the individual post files.
So this gives me all the post file names,
with the file extensions included though.
We should keep that in mind,
and therefore in slug JS,
I now can call, get posts files.
So I'll import that function
and call it, from the lib folder
and the posts-util file.
Now this will give me all the posts file names,
and here I'm actually just interested in the slugs.
So to file names without the extensions.
Hence I'll create a slugs constant.
And that's just as post file names,
where I map every file name,
such that I removed the extension.
So I'll just again, replace,
this regular expression,
which we also used here.
So I'll just copy that code in the end,
and replace that with an empty string.
So that now maps all my file names into, just slug strings.
And now we can generate paths here
by going through all the slugs,
and mapping every slug into, an object,
hence the, parentheses around it,
so that, this is not treated
as the function body,
but as an immediately returned object,
where we have the params key,
which holds another nested object,
where we set slug equal to, slug here.
And we could also do this in one step.
I'm doing it in two steps here
to make it a bit more readable.
So this will now generate an array of path objects,
and we are generating all our paths in advance.
So we are pre-generating this, single post page,
for all our posts in advance.
Now this should work.
In get static props,
we return our post prop.
So now we can use this here,
in the post detailed page and get props,
and set a post prop on post content,
and pass props.post into that,
and then go to post content,
to use this post prop instead
of the dummy post there.
So in post content,
I'll get rid of that dummy post,
and instead accept props here.
And then here, we can, first of all,
extract our posts from the props,
and then use, post.slug here,
and post.image, and here, post.title,
and of course here also, post.content.
If we do all of this,
if we save everything,
and reload this page, it should work.
We should see the image, the title
and the actual content
as we wrote it in the markdown file.
Now it is of course up to you,
to then add styling,
for the different content elements you might have.
You can do this with the post content module CSS file.
Here by using the content class,
and then selecting different elements in your content.
You can style them,
and change link colors,
change to display of tables,
whatever you might have.
But with that, we are fetching our actual post data.
And therefore now,
we can click on a post here,
see it, click on it here, see it.
And it just works.