Gatsby website failing to create slugs as anticipated

While trying to follow the Gatsby tutorial, I ran into an issue with generating slugs for MDX files in a subdirectory of src/pages. For instance, if I have a file like

src/pages/projects/devmarks/index.md
, the expected slug according to the tutorial should be devmarks, allowing me to access the page at localhost:8000/projects/devmarks. However, the actual slug ends up being projects/devmarks, resulting in only being able to reach the fully rendered page at
localhost:8000/projects/projects/devmarks
. Interestingly though, visiting localhost:8000/projects/devmarks displays the content of the MDX file but without proper rendering. It seems like the createPages function in gatsby-node.js or moving the {mdx.slug}.tsx file up one level might resolve this issue, however, I’m puzzled as to why my code isn’t behaving as expected based on the tutorial.

Full Source Code

gatsby-config.ts

import type { GatsbyConfig } from "gatsby";

const config: GatsbyConfig = {
    siteMetadata: {
        title: `Christopher Leggett's Portfolio and Blog`,
        description: `The Portfolio and Blog for the aspiring software developer Christopher Leggett`,
        siteUrl: `https://chrisleggett.me`,
        twitterUsername: `@leggettc18`
    },
    plugins: ["gatsby-plugin-image", "gatsby-plugin-react-helmet", "gatsby-plugin-postcss", {
        resolve: 'gatsby-plugin-manifest',
        options: {
            "icon": "src/images/icon.png"
        }
    }, "gatsby-plugin-mdx", "gatsby-plugin-sharp", "gatsby-transformer-sharp", {
            resolve: 'gatsby-source-filesystem',
            options: {
                "name": "images",
                "path": "./src/images/"
            },
            __key: "images"
        }, {
            resolve: 'gatsby-source-filesystem',
            options: {
                "name": "pages",
                "path": "./src/pages/"
            },
            __key: "pages"
        }]
};

export default config;

folder structure

- src
  - images
  - components
    - layout.tsx
  - css
    - index.css //contains tailwind stuff
  - pages
    - index.tsx
    - about.tsx
    - 404.tsx
    - projects
      - {mdx.slug}.tsx
      - devmarks
        - index.mdx

In the tutorial, they had configured the source-filesystem plugin to point at a src/blog directory, which was not updated when they moved all the content to src/pages/blog. Having read through the tutorial beforehand, I organized my portfolio projects directly in src/pages/projects. Could this difference in organization be causing the discrepancy in how my slugs are generated compared to the tutorial?

Answer №1

After going through the tutorial again, I realized my mistake. When it mentioned moving the blog.js and {mdx.slug}.js files into the src/pages/blog folder, I misunderstood and thought it was also relocating the actual blog content there. It turns out that the root blog (or in my case portfolio) folder still needs to exist and be configured by gatsby-source-filesystem as follows:

{
   "resolve": "gatsby-source-filesystem",
   "options": {
      "name": "portfolio",
      "path": `${__dirname}/content/portfolio/`
   }
}

I chose to place the portfolio folder under a content directory in anticipation of adding other types of content in the future.

filesystem

- content
  - portfolio
    - devmarks
      - index.mdx
- src
  - images
  - components
    - layout.tsx
  - css
    - index.css //contains tailwind stuff
  - pages
    - index.tsx
    - about.tsx
    - 404.tsx
    - projects
      - index.tsx
      - {mdx.slug}.tsx

Initially, I had placed the portfolio contents in .src/pages/portfolio, causing issues with the filesystem route API creating routes for the .mdx files separately. This resulted in displaying only the body of the mdx file and generating incorrect slugs for the actual pages due to the path from my pages directory.

As a tip for others using TypeScript, please note that the __dirname variable may return a folder within the .cache directory instead of the expected location. For more information on this behavior with TypeScript, refer to:

Answer №2

It seems like your configuration for gatsby-source-filesystem is incorrect. You should update it to:

{
   "resolve": "gatsby-source-filesystem",
   "options": {
      "name": "portfolio",
      "path": `${__dirname}/portfolio/`
   }
}

Pay attention to the crucial part which is setting path: `${__dirname}/portfolio/` . This information is necessary for Gatsby's filesystem to locate the content source folder.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Getting News API and showcasing the information in Vuetify.js card components: A step-by-step guide

I'm trying to develop a news website by utilizing the News API for news data. I obtained an API Key from the official News API website, but my code is encountering some issues. The error message reads: TypeError: response.data.map is not a function ...

Is it possible to locate a Typescript class only when there are no references to its properties?

Currently, I am utilizing TypeScript 2.0 within VSCode and although the highlighted errors are being confirmed by the TypeScript compiler, they all point to a module that I am importing: import * as els from 'elasticsearch'; The module elastics ...

VSCode still throwing a replaceAll warning, despite targeting ES2021

Here is the tsconfig file for my Vue project: { "extends": "@vue/tsconfig/tsconfig.web.json", "include": ["env.d.ts", "src/**/*", "src/**/*.vue", "src/**/*.json"], "exclude ...

What could be the rationale behind the optional chaining operator not being fully compatible with a union of classes in TypeScript?

Imagine I have a combination of classes: type X = ClassA | ClassB | ClassC; Both ClassA and ClassC have a shared method called methodY. Why is it that I can't simply use the optional chaining operator to call for methodY? class ClassA { methodY ...

Typescript fails to identify the parameter type of callbacks

I am facing a challenge with the function below and its callback type: type Callbacks = { onSuccess: (a: string) => void; }; function myFunction(event: string, ...args: [...any, Callbacks]) { } The function works correctly except for one issue - ...

Transferring information between screens in Ionic Framework 2

I'm a beginner in the world of Ionic and I've encountered an issue with my code. In my restaurant.html page, I have a list of restaurants that, when clicked, should display the full details on another page. However, it seems that the details for ...

Is there a way to dynamically exclude files from the TypeScript compiler?

Currently, I am in the process of setting up a node/typescript server for a real-time application. Both my server and client are located within the same folder. My goal is to exclude "src/client" from the typescript compiler when executing the "server:dev ...

Compose a message directed to a particular channel using TypeScript

Is there a way to send a greeting message to a "welcome" text channel whenever a new user joins the server (guild)? The issue I'm running into is that, when I locate the desired channel, it comes back as a GuildChannel. Since GuildChannel does not hav ...

What is the best way to incorporate TypeScript into a simple JavaScript project and release it as a JavaScript library with JSDoc for TypeScript users?

Issue: I have encountered difficulties finding an efficient solution for this. Here's a summary of what I attempted: To start, ensure that allowJs and checkJs are both set to true in the tsconfig.json, then include the project files accordingly. Ty ...

Using a comma as a decimal separator for input is not permitted when working with angular/typescript/html

I am facing an issue with my Angular frontend where I have numerous html input fields that trigger calculations upon typing. <input type="text" [(ngModel)]="myModel.myAttribute" (input)="calculate()"> The problem arise ...

Remove an item from an array within Express using Mongoose

{ "_id": "608c3d353f94ae40aff1dec4", "userId": "608425c08a3f8db8845bee84", "experiences": [ { "designation": "Manager", "_id": "609197056bd0ea09eee94 ...

Experiencing a useContext error when implementing MDX with NextJS 13

I am currently working on integrating mdx files into Next.js 13. After completing all necessary configurations in next.config and creating the file structure, I have the following path within the app folder: > docs > components > accordion > pa ...

What is the best way to kickstart a Reactive Angular 2 form by utilizing an Observable?

My current strategy involves storing the form values in my ngrx store so that users can easily navigate around the site and return to the form if needed. The concept is to have the form values repopulate from the store using an observable. This is how I a ...

Issue: Typescript/React module does not have any exported components

I'm currently facing an issue with exporting prop types from one view component to another container component and using them as state type definitions: // ./Component.tsx export type Props { someProp: string; } export const Component = (props: ...

Updating the style of different input elements using Angular's dynamic CSS properties

I am seeking guidance on the proper method for achieving a specific functionality. I have a set of buttons, and I would like the opacity of a button to increase when it is pressed. Here is the approach I have taken so far, but I have doubts about its eff ...

Verification based on conditions for Angular reactive forms

I am currently learning Angular and working on creating a reactive form. Within my HTML table, I have generated controls by looping through the data. I am looking to add validation based on the following cases: Upon page load, the Save button should be ...

The implementation of conditional parameter types in TypeScript

I am struggling with a function where the type of the first argument is determined by the second argument's value of true or false According to my logic, if userExists is true, data should be a string and if it's false, data should be a number. ...

Steps for incorporating a type declaration for an array of objects in a React application with TypeScript

How can I specify the type for an array of objects in React using TypeScript? Here is the code snippet: const SomeComponent = (item: string, children: any) => { //some logic } In this code, you can see that I am currently using 'any' as ...

Switch app engines in real-time based on the URL path with express framework

How can I dynamically set App Engine based on the URL? In my application, I have two render engines available: serverSideRenderEngine & browserRenderEngine If the URL is /home, the app.engine should be set as serverSideRenderEngine If the URL is /l ...

Make sure to declare rest parameters first when using Typescript

I am dealing with a function that takes in multiple string arguments and one final argument of a complex type, which is called Expression. This particular code looks like this in JavaScript: function layerProp(...args) { const fields = args.slice(0, -1) ...