This website is a work in progress.

Setup a global layout with a common header and footer

Setup a global layout with a common header and footer

Simple problem means simple solution: you need to use a common wrapper component.

import Head from "react-helmet";
 
const Layout = ({ children }) => (
  <div>
    <Head>
      <html lang="en" /> {/* this is valid react-helmet usage! */}
      <meta charSet="utf-8" />
      <meta name="viewport" content="width=device-width, initial-scale=1" />
    </Head>
    <header>{/* ... */}</header>
    <div>{children}</div>
    <footer>{/* ... */}</footer>
  </div>
);

Now you can replace previous <div> used in previous example:

const Home = ({ posts }) => <Layout>{/* .... */}</Layout>;
 
// ...
 
const BlogPost = ({ page }) => <Layout>{/* .... */}</Layout>;

If you need different layouts, you can just use a common base component, and do some alternatives based on it.

If you want to specify layout from markdown files, you can handle this yourself in your component specified in your routes.

Here is a simple implementation

// ...
const DefaultPostLayout = ({ title, body }) => (
  <article>
    <Head>
      <title>{title}</title>
      <meta
        name="description"
        content={textRenderer(body).slice(0, 150) + ""}
      />
    </Head>
    <h1>{title}</h1>
    <BodyRenderer>{body}</BodyRenderer>
  </article>
);
 
const HeroPostLayout = ({ title, body }) => (
  <article>
    <Head>
      <title>{title}</title>
      <meta
        name="description"
        content={textRenderer(body).slice(0, 150) + ""}
      />
    </Head>
    <div style={{ padding: "4rem", background: "pink", color: "#fff" }}>
      <h1>{title}</h1>
    </div>
    <BodyRenderer>{body}</BodyRenderer>
  </article>
);
 
const PostLayouts = {
  default: DefaultPostLayout,
  hero: HeroPostLayout
};
 
const BlogPost = ({ isLoading, page }) => {
  const PostLayout =
    (page.node && PostLayouts[page.node.layout]) || PostLayouts.default;
  return (
    <Layout>
      {isLoading && "Loading..."}
      {!isLoading && page.node && <PostLayout {...page.node} />}
      <footer>
        <Link to="/">Go to home</Link>
      </footer>
    </Layout>
  );
};

Then to use it, you can just add a layout property in your front-matter

---
title: Another post
layout: hero
---
 
Blah blah...

(Feel free to name the layout property how you prefer (eg: type)).


Continue tutorial