Mukhtar Bahadory

Contents

Optional Catch All v1

For this approach, I was under the assumption that I once I exposed all discovered paths to getStaticPaths, then on the index route, I would have access to ALL paths discovered. During the testing phase, I realized that my assumption of the index receiving all paths was not true and I did not proceed further.

Fixed Depth and Pre-determined Folders v2

This one was pretty decent and I wrote quite a lot of code for it. Essentially, there were three dynamic routes at play. The topic, subtopic, and subject.

I had included index routes for each of the dynamic slugs and was planning on filling them out but overall the idea still made me feel really boxed in with not a lot of room for flexibility. This edition was actually fully coded out and was in production for a few days before I finally decided it was inadequate.

The algorithm for it was essentially the following. I was able to tell the function essentially what depth I wanted to traverse to and it would take care of the rest and depending on the desired depth, it would expose the appropriate data.

export function exposeAllPossiblePostPaths(cb, { topics: wantsTopics, subtopics: wantsSubtopics, subjects: wantsSubjects }) {
  const topics = fs.readdirSync(postsDirectory)

  if (wantsTopics || wantsSubtopics || wantsSubjects) {
    for (const topic of topics) {
      const subtopicsDir = `${postsDirectory}/${topic}`
      const subtopics = fs.readdirSync(subtopicsDir)
      wantsTopics && cb(subtopicsDir, { topic })

      if (wantsSubtopics || wantsSubjects) {
        for (const subtopic of subtopics) {
          const subtopicDir = `${subtopicsDir}/${subtopic}`
          const subjects = readdirSync(subtopicDir)

          wantsSubtopics && cb(subtopicDir, { topic, subtopic })

          if (wantsSubjects) {
            for (const subject of subjects) {
              const subjectDir = `${subtopicDir}/${subject}`
              const subjectNoExt = path.basename(subjectDir, '.md')

              wantsSubjects && cb(subjectDir, { topic, subtopic, subject: subjectNoExt })

            }
          }


        }
      }
    }
  }

}

Recursive Find on Blog Directory and Finding Files v3

This approach was in the right direction. At this point, I could have basically any folder structure but I still had a really poor limitation. I could not have two files with the same name, even if they were in completely different directories. The slug exposed to getStaticPaths was essentially a unique filename and with that I had to implement another recursive function to pull the respective file.

It was a pretty fun version to play around with especially because I had the opportunity to play around quite a bit with tree algorithms, but I still had to find a different way of doing it as it was still not optimal.

Recursive Find On Blog Directory and Finding Paths v4

For this approach, instead of exposing a filename to getStaticPaths, I exposed an entire path. This had a really neat advantage that feels really natural; the only time you can't have two files of the same name is if they're in the same directory. That is a limitation that is beyond the implementation, it is something relating to the operating system itself.

The above advantage and the fact that I can nest my folder structure as deeply as I wish and still rest assured that the slugs will be created feel really good when adding any new entry to the blog.

The algorithm for getStaticPaths is as follows. Pretty neat huh?

export async function exposeAllPostSlugsAndPaths(dir = postsDirectory) {
  const contents = await fsAsync.readdir(dir)
  let fileResultsContainer = []

  for (const potentialFileOrDir of contents) {
    const potentialFileOrDirPath = `${dir}/${potentialFileOrDir}`
    const stats = await fsAsync.lstat(potentialFileOrDirPath)

    if (stats.isDirectory()) {
      fileResultsContainer = fileResultsContainer.concat(await exposeAllPostSlugsAndPaths(draftMode, all, potentialFileOrDirPath))
    } else {
      fileResultsContainer.push(getSlugAndPath(potentialFileOrDirPath))
    }
  }

  return fileResultsContainer
}