How to create Custom Pages?

Hello @luisherranz, I tried your solution but when I am typing any id I get a 404 page :confused:

  const helloHandler = {
  pattern: "/hello/:id",
  func: ({ state, link, params }) => {
    state.source.data[link].isHello = true;
    state.source.data[link].id = params.id;
  },
};

And

packages: [
{
  name: "@awsmin/f1",
  state: {
    theme: {
      menu: [
        ["Nos occasions", "/"],
        ["L'atelier", "/category/nature/"],
        ["Nos services", "/category/travel/"],
        ["Qui sommes-nous", "/tag/japan/"],
        ["Actualités", "/about-us/"],
        ["Nous contacter", "/about-us/"],
      ],
      featured: {
        showOnList: false,
        showOnPost: false,
      },
    },
  },
  actions: {
    theme: {
      init: ({ libraries }) => {
        // Use html2react to process the <img> tags inside the content HTML.
        // libraries.html2react.processors.push(image);

        // Add the handler to wp-source.
        libraries.source.handlers.push(helloHandler);
      },
    },
  },

and my index.js I create a component with sample h1 at that time

<Switch>
      <Loading when={data.isFetching} />
      <List when={data.isArchive} />
      <HomeScreen when={data.isHome} />
      <VehicleScreen when={data.isOffers} />
      <Entretien when={data.isEntretien} />
      <Hello when={data.isHello} />
      <Jobs when={data.isAwsmJobOpenings} />
      <Page when={data.isPage} />
      <Post when={data.isPostType} />
      <PageError when={data.isError} />
    </Switch>
1 Like

Hi @floriandupuis1996,

Can you please provide a repo or code-sandbox with your code? This is especially helpful to find solutions of technical issues with specific code

I use it, can fix this problem !

const profilePage = {
	name: 'member',
	priority: 1,
	pattern: '/member/:user',
	func: ({ state, link, params }) => {
		state.source.data[link].isProfile = true
		state.source.data[link].user = params.user
	},
}
]
	actions: {
		actions: {
			init: ({ libraries }) => {
				libraries.source.handlers.push(profilePage)
			},
		},
		theme: {
...
}

Yeah I succeed

Hey @floriandupuis1996 it’d be great if you can share with the rest how you finally solved and what was the issue you were having :smiley:

Ths thing is I had handler in frontity.settings.js instead of index… now I am looking to get the param.id display on my component but this is not easy task…

any idea ?

Hi there, I’m Pilar. I’m starting with Frontity and I’ve struggling with custom handlers, custom pages and custom queries, browsing this thread and many others, reading the docs, etc. I’ve finally made it work so I wanted to share the code in case it’s helpful for anyone, as yours has been to me :slight_smile:

The base of my project is a large set of Galician traditional sayings or “refranes”. The main user interaction will be the search (and also copying the text of the quote, sharing it as an image, etc. but that’s another story). For SEO reasons I want some popular searches to be on the menu and have their own url, like “sayings-about-winter” (instead of “domain.com/?s=winter”), without having to categorize them. So I created a custom handler that takes the last word of that url pattern, whatever it is, (in this case, “winter”) and shows all the posts that contain that specific word.

That’s how I achieved it, I don’t know if it’s a better way to to do it? It would be simpler with the future method described here, but for now it’s working :slight_smile:!

In mars-theme/src/index.js:

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

const searchUrls = {
  priority: 1,
  pattern: "/sayings-about-:search",
  func: async ({ link, params, state, libraries, force }) => {
    
    const response = await libraries.source.api.get({
      endpoint: "posts",
      params: { search: params.search }
    });

    const items = await libraries.source.populate({
      response,
      state,
      force,
    });    

    Object.assign(state.source.data[link], {
      isSearchUrl: true,
      //add queried posts to data
      items,
    });

  }
}
const marsTheme = {
  name: "@frontity/mars-theme",
  roots: {
    theme: Theme,
  },
  state: {
    theme: {

      },
    },
  },
  actions: {
    theme: {   
      init: ({ libraries }) => {
        libraries.source.handlers.push(searchUrls);
      },    
    },
  },
};

export default marsTheme;

In src/components/index.js:

<Switch>
  <Loading when={data.isFetching} />
  <List when={data.isArchive} />
  <Post when={data.isPostType} />
  <ListSearch when={data.isSearchUrl} />
</Switch>

In components/list/list-search.js:

const ListSearch = ({ state, libraries, link }) => {
    const data = state.source.get(state.router.link);
    return (
      <Container>
        {data.items.map(({ type, id }) => {
          const item = state.source[type][id];
          // Render one Item component for each one.
          return <Item key={item.id} item={item} />;
        })}
        <Pagination />
      </Container>
    );
};

Now if I go to /sayings-about-winter I see all the posts that contain the word “winter”, and /sayings-about-spring shows all the posts containing “spring”, etc.

And I can add these links to the menu in frontity.settings.js (or anywhere else):

      "menu": [
        [
          "Home",
          "/"
        ],
        [
          "Sayings about winter",
          "/sayings-about-winter/"
        ],
        [
          "Sayings about spring",
          "/sayings-about-spring/"
        ],
      ],
4 Likes

Hi @decrecementofeliz

Welcome to the community. It looks like you’re doing great on your journey with Frontity! :tada:

Thanks for presenting this solution. I’m sure other Frontity users will find it useful.

We’d love to know more about what you’re building with Frontity. We’re always looking for projects to feature in our showcase page.

2 Likes

Hi, here is my frontity page: http://api-tech.pl/ but I have problem with routes,

I can’t get to the site directly from the link for example http://api-tech.pl/kontakt give me 404;
also when I’m for example first render FOTOGRAFIA > PODLASIE (PHOTOGRAPHY > PODLASIE)
looks good, and after refresh my gallery disappear.
I thought something wrong in Theme index.js and with handlers

 <Main>

 {data.isPodlasiePage && <PodlasiePage />} 
      {data.isFrontPage && <Home />}  
      {data.isGoryPage && <GoryPage />} 
      {data.isTimelapsePage && <TimelapsePage />}
      {data.isCommercialPage && <ComercialMoviesPage />}
      {data.isGoPodlasiePage && <GoPodlasiePage />}
      {data.isColaboPage && <CollaborationPage />}
      {data.isContactPage && <ContactPage />} 
      {data.isPolitykaPage && <PrivacyPolicyPage />}

<Switch>
  <Loading when={data.isFetching} />
  <List when={data.isArchive} />
  <PageError when={data.isError} />
</Switch>

and here:

const homeHandler = {

  pattern: "/",

  func: ({ state }) => {

    state.source.data["/"].isFrontPage = true;

    state.source.data["/"].isArchive = false;

  }

}

const fotografiaHandler = {

  pattern: "/fotografia/",

  func: ({ state }) => {

    state.source.data["/astrofoto/"].isShovvPage = true;

    state.source.data["/astrofoto/"].isArchive = false;

  }

}

const podlasieHandler = {

  pattern: "/podlasie/",

  func: ({ state }) => {

    state.source.data["/podlasie/"].isPodlasiePage = true;

    state.source.data["/podlasie/"].isArchive = false;

  }

}

// const astroHandler = {

//   pattern: "/astrofoto/",

//   func: ({ state }) => {

//     state.source.data["/astrofoto/"].isAstroPage = true;

//     state.source.data["/astrofoto/"].isArchive = false;

//   }

// }

const goryHandler = {

  pattern: "/gory/",

  func: ({ state }) => {

    state.source.data["/gory/"].isGoryPage = true;

    state.source.data["/gory/"].isArchive = false;

    // state.source.data["/gory/"].isPostType = false;

  }

}

const wadirumHandler = {

  pattern: "/wadirum/",

  func: ({ state }) => {

    state.source.data["/wadirum/"].isWadirumPage = true;

    state.source.data["/wadirum/"].isArchive = false;

    console.log('inside handler')

  }

}

const colaboHandler = {

  pattern: "/wspolpraca/",

  func: ({ state }) => {

    state.source.data["/wspolpraca/"].isColaboPage = true;

    state.source.data["/wspolpraca/"].isArchive = false;

  }

}

const timelapseHandler = {

  pattern: "/timelapse/",

  func: ({ state }) => {

    state.source.data["/timelapse/"].isTimelapsePage = true;

    state.source.data["/timelapse/"].isArchive = false;

  }

}

const commercialHandler = {

  pattern: "/komercyjne/",

  func: ({ state }) => {

    state.source.data["/komercyjne/"].isCommercialPage = true;

    state.source.data["/komercyjne/"].isArchive = false;

  }

}

const goPodlasieHandler = {

  pattern: "/go-podlasie/",

  func: ({ state }) => {

    state.source.data["/go-podlasie/"].isGoPodlasiePage = true;

    state.source.data["/go-podlasie/"].isArchive = false;

  }

}

const contactHandler = {

  pattern: "/kontakt/",

  func: ({ state }) => {

    state.source.data["/kontakt/"].isContactPage = true;

  }

}

const privacyPolicyHandler = {

  pattern: "/polityka-prywatnosci/",

  func: ({ state }) => {

    state.source.data["/polityka-prywatnosci/"].isPolitykaPage = true;

    state.source.data["/polityka-prywatnosci/"].isArchive = false;

  }

}

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;

      },

      init: ({ libraries }) => {

        // Use html2react to process the <img> tags inside the content HTML.

        libraries.html2react.processors.push(image);

        // Add the handler to wp-source.

        libraries.source.handlers.push(homeHandler);

        libraries.source.handlers.push(fotografiaHandler);

        libraries.source.handlers.push(podlasieHandler);

        // libraries.source.handlers.push(astroHandler);

        libraries.source.handlers.push(goryHandler);

        libraries.source.handlers.push(wadirumHandler);

        libraries.source.handlers.push(colaboHandler);

        libraries.source.handlers.push(timelapseHandler);

        libraries.source.handlers.push(commercialHandler);

        libraries.source.handlers.push(goPodlasieHandler);

        libraries.source.handlers.push(contactHandler);

        libraries.source.handlers.push(privacyPolicyHandler);

        console.log('init')

      },

      

      beforeSSR: async ({actions}) => {

         await actions.source.fetch("/contact");

         await actions.source.fetch("/gora");

        }

      },

    },

also in my index.js I used the approach below with same effect.

 <ContactPage when={data.isContactPage}/>
  <Home when={data.isFrontPage}/>
  <PodlasiePage when={data.isPodlasiePage}/>

Can anybody tell me how to get it right?

Looks like it’s working now, maybe you fixed it already

Hi @rborowski.shovv,

As @furrysmile2 says, your categories links seem to be working fine from both Server side and Client Side navigation

Is it working now for you?

Yes, it’s working well. Last thing is that after refreshing page for exmaple http://api-tech.pl/kontakt in Firefox, losing styles of material ui icons, and get huge

3 posts were split to a new topic: 404 page since updating to latest Frontity

A post was split to a new topic: Custom path is leading to the 404 page