Configuring custom layout for homepage in Next.js Landing Pages Template.

7 replies
Last updated: Aug 31, 2020
Happy Friday 👋 - I am using the Next.js Landing Pages Template. At the moment all pages default to the 'LandingPage' layout, however I'd like to create a custom layout just for my homepage (to hide the footer etc). Is there a way for me to configure this? To direct 'frontpage' and '/' to the CustomLayout.js rather than the LandingPage.js?
AI Update

Great question! Yes, you can definitely configure a custom layout for your homepage in the Next.js Landing Pages Template. Based on a previous discussion about this exact issue, here's how to do it:

Solution: Edit your next.config.js

The template uses the next.config.js file to map routes to page templates. By default, all routes (including /) use the LandingPage template, except /custom-page which uses the CustomPage template.

To direct your homepage to a custom layout:

  1. Modify the exportPathMap function in your next.config.js to map the root path (/) to your custom page:
exportPathMap: function () {
  return client.fetch(query).then((res) => {
    const { routes = [] } = res;
    const nextRoutes = {
      // Routes imported from sanity
      ...routes.filter(({ slug }) => slug.current).reduce(reduceRoutes, {}),
      "/": { page: "/CustomPage" }, // Add this line
    };
    return nextRoutes;
  });
}
  1. Create your custom layout in the CustomPage.js file (or create a new one) where you can hide the footer or make any other layout changes specific to your homepage.

Alternative Approach

If you only need to hide the footer on the homepage, you could also check the current slug inside the LandingPage component and conditionally show/hide the footer based on whether you're on the homepage:

{router.query.slug !== '/' && <Footer />}

This approach is simpler if you just need minor variations rather than a completely different layout.

Note: This template uses an older Next.js Pages Router pattern with exportPathMap. If you're working with a newer Next.js setup, you'd typically handle this through the file-based routing system or dynamic routes instead.

Hi User, this should be possible by editing your
next.config.js
file. By default it uses the
LandingPage
template for all routes including
/
, with the exception of
/custom-page
, which gets the
CustomPage
template. You could edit how it builds the routes here.
Alternatively, you might be able to simply check for current slug inside
LandingPage
and show/hide the footer accordingly, for example.
Let me know if that gives you enough hints to go on
🙂
Hi User, this should be possible by editing your
next.config.js
file. By default it uses the
LandingPage
template for all routes including
/
, with the exception of
/custom-page
, which gets the
CustomPage
template. You could edit how it builds the routes here.
Alternatively, you might be able to simply check for current slug inside
LandingPage
and show/hide the footer accordingly, for example.
Let me know if that gives you enough hints to go on
🙂
Perfect thanks User, I've directed the homepage to custompage and created a specific layout for this now. All working 🙌
Awesome, User 🎉 Happy Friday to you too!
Hey
user M
- me again. I've run into an issue with my routing to custom page. As mentioned I redirected the '/' slug to go to the custom-page and made a new template in there just for the homepage (so I could hide the footer. It works fine when you access the homepage from the navigation HOWEVER if you just hit localhost:3000 it goes to a blank page. I'm guessing there is some more config I need to do?
My next.config.js

const withCSS = require("@zeit/next-css");
const client = require("./client");

const isProduction = process.env.NODE_ENV === "production";
const query = `
{
  "routes": *[_type == "route"] {
    ...,
    disallowRobot,
    includeInSitemap,
    page->{
      _id,
      title,
      _createdAt,
      _updatedAt
  }}
}
`;

const reduceRoutes = (obj, route) => {
  const { page = {}, slug = {} } = route;
  const { _createdAt, _updatedAt } = page;
  const { includeInSitemap, disallowRobot } = route;
  const path = route["slug"]["current"] === "/" ? "/" : `/${route["slug"]["current"]}`;
  obj[path] = {
    query: {
      slug: slug.current,
    },
    includeInSitemap,
    disallowRobot,
    _createdAt,
    _updatedAt,
    page: "/LandingPage",
  };
  return obj;
};

module.exports = withCSS({
  cssModules: true,
  cssLoaderOptions: {
    importLoaders: 1,
    localIdentName: isProduction ? "[hash:base64:5]" : "[name]__[local]___[hash:base64:5]",
  },
  exportPathMap: function () {
    return client.fetch(query).then((res) => {
      const { routes = [] } = res;
      const nextRoutes = {
        // Routes imported from sanity
        ...routes.filter(({ slug }) => slug.current).reduce(reduceRoutes, {}),
        "/": { page: "/CustomPage" },
      };
      return nextRoutes;
    });
  },
});
my Header.js
import React, { Component } from "react";
import PropTypes from "prop-types";
import Link from "next/link";
import { withRouter } from "next/router";
import SVG from "react-inlinesvg";
import styles from "./Header.module.css";
import HamburgerIcon from "./icons/Hamburger";

class Header extends Component {
  state = { showNav: false };

  static propTypes = {
    router: PropTypes.shape({
      pathname: PropTypes.string,
      query: PropTypes.shape({
        slug: PropTypes.string,
      }),
      events: PropTypes.any,
    }),
    title: PropTypes.string,
    navItems: PropTypes.arrayOf(
      PropTypes.shape({
        title: PropTypes.string.isRequired,
        slug: PropTypes.shape({
          current: PropTypes.string,
        }).isRequired,
      })
    ),
    logo: PropTypes.shape({
      asset: PropTypes.shape({
        url: PropTypes.string,
      }),
      logo: PropTypes.string,
    }),
  };

  componentDidMount() {
    const { router } = this.props;
    router.events.on("routeChangeComplete", this.hideMenu);
  }

  componentWillUnmount() {
    const { router } = this.props;
    router.events.off("routeChangeComplete", this.hideMenu);
  }

  hideMenu = () => {
    this.setState({ showNav: false });
  };

  handleMenuToggle = () => {
    const { showNav } = this.state;
    this.setState({
      showNav: !showNav,
    });
  };

  renderLogo = (logo) => {
    if (!logo || !logo.asset) {
      return null;
    }

    if (logo.asset.extension === "svg") {
      return <SVG src={logo.asset.url} className={styles.logo} />;
    }

    return <img src={logo.asset.url} alt={logo.title} className={styles.logo} />;
  };

  render() {
    const { title = "Missing title", navItems, router, logo } = this.props;
    const { showNav } = this.state;

    return (
      <div className={styles.root} data-show-nav={showNav}>
        <h1 className={styles.branding}>
          <Link
            href={{
              pathname: "/CustomPage",
              query: {
                slug: "/",
              },
            }}
            as="/"
            prefetch
          >
            <a title={title}>{this.renderLogo(logo)}</a>
          </Link>
        </h1>
        <nav className={styles.nav}>
          <ul className={styles.navItems}>
            {navItems &&
              navItems.map((item) => {
                const { slug, title, _id } = item;
                const isActive =
                  router.pathname === "/LandingPage" && router.query.slug === slug.current;
                return (
                  <li key={_id} className={styles.navItem}>
                    <Link
                      href={{
                        pathname: "/LandingPage",
                        query: { slug: slug.current },
                      }}
                      as={`/${slug.current}`}
                      prefetch
                    >
                      <a data-is-active={isActive ? "true" : "false"}>{title}</a>
                    </Link>
                  </li>
                );
              })}
          </ul>
          <button className={styles.showNavButton} onClick={this.handleMenuToggle}>
            <HamburgerIcon className={styles.hamburgerIcon} />
          </button>
        </nav>
      </div>
    );
  }
}

export default withRouter(Header);
I’m having the same issue with blank page when hitting: localhost:3000. Actually I get this message
No route set
Setup automatic routes in sanity or custom routes in next.config.js

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?