WordPress URLs ending in .html

Thank you @hsbas :blush:

Just let us know if the problem persists. We’ll try to solve it asap in that case.

2 Likes

Hi there,

Your new documentation prepared very well, congratulations and thank you.

I created the project just like on this page. All I did was use the command frontity create and then replace state.source.url with my site. Then I ran the server with the frontity dev command.

The site opened at localhost:3000 looks normal. But when I go into an article and refresh the page, I get a 404 error. If I don’t refresh the page, it’s okay. However, when I want to go back and open the page again I get a 404 error. This problem happens only on my WordPress address. What could the problem be about and how can I solve it?

Hi @hsbas,

I’ve used the Frontity CodeSandbox boilerplate to create a Frontity project where i just have changed the state.source.api setting to point to https://koinbulteni.com/wp-json

    {
      name: "@frontity/wp-source",
      state: {
        source: {
          api: "https://koinbulteni.com/wp-json"
        }
      }
    },

This is the codesandbox deployed version of the mars-theme using your WP REST API → https://lt0wk.sse.codesandbox.io/

You’re right with the behaviour of your final site.

I guess the error must come from the .html generated for each url.
Is this final .html added for a specific reason from your WordPress? You don’t really need that extension at the end of the URL and I think SEO would even be better without it

1 Like

@cristianbote It seems URL’s defined with a specific extension (.html in this case) doesn’t load properly from SSR rendering

Can you check this to decide if this is a bug that need to be addressed or if this is something we should explain in our documentation

1 Like

HÄ° @juanma,

Thank you for your interest and detailed explanation.

We do not have a special reason to use the .html extension, but the link structure has been like this for 4 years. It would not be healthy to update the link structure as “post name” as stated in the document, because we have more than 20,000 articles. So the only thing we can do is remove the “.html” at the end of the link.

But you will appreciate that making such a link structure change directly on an authoritative site like this can be risky for Google indexes.

I am very hesitant about what I should do.

Hi @hsbas, I am looking into it.

Meanwhile I’ve found this community question How do I link to my WordPress pages (not posts) that have a .htm extension in the URL?, where @mmczaplinski linked to post about how from a SEO point of view, the document extensions are ignored https://www.searchenginejournal.com/googles-john-mueller-says-parameters-urls-not-matter/246675/#close.

Open up a bug to track this further Navigating to a Server Side Rendered url with an extension, `.html`, shows 404 page · Issue #727 · frontity/frontity · GitHub

Hi @cristianbote

I will be excitedly waiting for the problem to be solved.

Thanks!

Hi @hsbas,

There’s been some more progress on the issue and the fix it’s fairly straight. Would you be open to contribute with the fix yourself? :grinning_face_with_smiling_eyes:

We would love and welcome any contribution! We have a fairly easy to start contribution guide. There’s nothing else like fixing an issue on an open-source software. :muscle:

Let me know if there’s more that I can do in here.
Have a great one!

2 Likes

@hsbas I’ve just realized that you can also do this in a package, modifying the handlers in the init function:

export default {
  actions: {
    myPackage: {
      init: ({ libraries }) => {
        libraries.source.handlers.map((handler) => {
          handler.pattern += "(\\.html)?";
          return handler;
        });
      },
    },
  },
};

Could you please try it out and let us know if it works?

Hi Luis,

I tried this in mars-theme index.js file. It didn’t work. I also tried in console but nothing changed. I can reach the same post multiple times with different browser tabs but when I press refresh button, it gives me 404 error.

Did you tried this action? Maybe I’m missing something. :sweat_smile:

I think the issue is because we are using the init function, which doesn’t guarantee that the libraries from other packages have been initialized. In this case the handlers from wp-source.

In Frontity, the packages are initialized in the order they are defined in the frontity.settings.js file. In the case of the default mars-theme, the theme is before the wp-source package. This means that when we call the init function of the theme, the handlers don’t exist yet.

There are two easy ways of solving this:

export default {
  actions: {
    myPackage: {
      beforeSSR: ({ libraries }) => {
        libraries.source.handlers.map((handler) => {
          handler.pattern += "(\\.html)?";
          return handler;
        });
      },
    },
  },
};

  • Move the wp-source package to the top of the frontity.settings.js file so it is initialized before the theme.

I’ve tested both and they seem to work fine for me, but I guess that using beforeSSR is safer.

Could you please test if this works for you as well @hsbas ? :slightly_smiling_face:

1 Like

Hi,

I guess I didn’t understand exactly where to use these actions. When I check “frontity.libraries.source.handlers” value at the console, I don’t see handlers ending with “.html”.

For mars-theme, can you tell me where I should place this action you’ve sent?

For mars-theme, can you tell me where I should place this action you’ve sent?

Sure! In the case of the default mars-theme I think you could edit the index.js file. This could be it:

import Theme from "./components";
import image from "@frontity/html2react/processors/image";
import iframe from "@frontity/html2react/processors/iframe";
import link from "@frontity/html2react/processors/link";

const marsTheme = {
  name: "@frontity/mars-theme",
  roots: {
    /**
     * In Frontity, any package can add React components to the site.
     * We use roots for that, scoped to the `theme` namespace.
     */
    theme: Theme,
  },
  state: {
    /**
     * State is where the packages store their default settings and other
     * relevant state. It is scoped to the `theme` namespace.
     */
    theme: {
      autoPrefetch: "in-view",
      menu: [],
      isMobileMenuOpen: false,
      featured: {
        showOnList: false,
        showOnPost: false,
      },
    },
  },

  /**
   * Actions are functions that modify the state or deal with other parts of
   * Frontity like libraries.
   */
  actions: {
    theme: {
      toggleMobileMenu: ({ state }) => {
        state.theme.isMobileMenuOpen = !state.theme.isMobileMenuOpen;
      },
      closeMobileMenu: ({ state }) => {
        state.theme.isMobileMenuOpen = false;
      },
      beforeSSR: ({ libraries }) => {
        libraries.source.handlers.map((handler) => {
          console.log(handler.pattern);
          handler.pattern += "(\\.html)?";
          return handler;
        });
      },
    },
  },
  libraries: {
    html2react: {
      /**
       * Add a processor to `html2react` so it processes the `<img>` tags
       * and internal link inside the content HTML.
       * You can add your own processors too.
       */
      processors: [image, iframe, link],
    },
  },
};

export default marsTheme;

2 Likes

Yes, I did it the same way. But for some reason, nothing changed:

Oh, I see. I just checked that the post was loading correctly in SSR.

With the second option I suggested, using the init function instead of beforeSSR, but moving the wp-source package before the mars-theme package in the frontity.settings.js file, it seems to appear also in the console. Did that work for you?

@luisherranz Do you know the pros and cons of each approach? Should we go back to initial idea of modifying the pattern in wp-source directly?

In this case, it works for the first page. But the same problem occurs when I surf between pages and refresh.

You’re right. I’ve noticed that it only works for the latest post. The older ones don’t work in SSR with these solutions. I’ve written what I found in the issue to keep researching the issue there.

The ending .html is not the only change to the URLs of that site. It also contains the post id and the slug is not complete, so it can’t be used.

I have made a video to explain a possible solution. It also contains the configuration for the tags and categories.

This is the init function:

init: ({ libraries }) => {
  const { handlers } = libraries.source;
  const postTypeHandler = handlers.find((h) => h.name === "post type");
  const tagHandler = handlers.find((h) => h.name === "tag");
  const categoryHandler = handlers.find((h) => h.name === "category");

  // Configure the post type URLs.
  postTypeHandler.pattern = "/(.*)?/:slug-:id(\\d+).html";
  postTypeHandler.priority = 20;

  // Add tag + category handler.
  handlers.push({
    name: "category + tag",
    priority: 30,
    pattern: "/:slug",
    func: async (...args) => {
      try {
        await tagHandler.func(...args);
      } catch (e) {
        await categoryHandler.func(...args);
      }
    },
  });
};

It wouldn’t work as it is because it would require that our postTypeHandler checks if there is a params.id and use that instead of the params.slug to retrieve the content from the REST API. But I think a change like that would make sense. It is also explained in the video.

The code would be something like this:

const apiParams = { _embed: true, ...state.source.params };
params.id ? (apiParams.include = params.id) : (apiParams.slug = params.slug);

const response = await libraries.source.api.get({
  endpoint,
  params: apiParams,
});

EDIT: @hsbas how are the URLs of the pages? They also need /:slug?

1 Like

Can i use this one code for only pages ?

Thank you.