Warning
You are browsing a legacy documentation for FTW (daily, hourly and product) which is no longer maintained.

Last updated

How to add static pages in FTW

This guide describes how to add pages with static content in Flex Template for Web (FTW).

Table of Contents

If you want to create simple pages that just show static content without need for data fetches, you can create a static page.

You might want to do this, for instance, if

  • you have a page that embeds a component that fetches its own data, or
  • you want to optimise some pages for performance, so that they don't fetch any data.

1. Create a new folder

Create a new folder under src/containers/ with the name of your static page. E.g. if you are creating a page for embedding your social media feeds, it should be named SocialMediaPage.

2. Create a JavaScript file

Create a new JavaScript file using the folder name. The path should look like src/containers/SocialMediaPage/SocialMediaPage.js.

3. Create a CSS file

Create a new CSS file using the folder name. The path should look like src/containers/SocialMediaPage/SocialMediaPage.module.css.

4. Create the component

Template for a single column static page (SocialMediaPage.js): (We'll go through this line-by-line below.)

import React from 'react';
import {
  LayoutSingleColumn,
  LayoutWrapperTopbar,
  LayoutWrapperMain,
  LayoutWrapperFooter,
  Footer,
  NamedLink,
  ExternalLink,
} from '../../components';

import StaticPage from '../../containers/StaticPage/StaticPage';
import TopbarContainer from '../../containers/TopbarContainer/TopbarContainer';

import css from './SocialMediaPage.module.css';
import image from './path/to/image.png';

const SocialMediaPage = () => {
  return (
    <StaticPage
      className={css.root}
      title="Social media"
      schema={{
        '@context': 'http://schema.org',
        '@type': 'SocialMediaPage',
        description: 'Description of this page',
        name: 'Social media page',
      }}
    >
      <LayoutSingleColumn>
        <LayoutWrapperTopbar>
          <TopbarContainer />
        </LayoutWrapperTopbar>
        <LayoutWrapperMain>
          <!-- You will add your embedding widgets here -->
          <div>
            <NamedLink name="LandingPage">Go to home page</NamedLink> or
            <ExternalLink href="https://google.com">
              Go to Google
            </ExternalLink>
          </div>
        </LayoutWrapperMain>
        <LayoutWrapperFooter>
          <Footer />
        </LayoutWrapperFooter>
      </LayoutSingleColumn>
    </StaticPage>
  );
};

export default SocialMediaPage;

We are using React and JSX to create components and pages. Therefore, we need to import React to our new component which is done in the first line.

import React from 'react';

Import components

In the second line we import some components:

  • LayoutSingleColumn and wrappers that it needs to position content
  • Footer component (to be added inside LayoutWrapperFooter)
  • NamedLink makes it easier to point to different pages inside the application
  • ExternalLink can be used to link outside the application. It creates a normal <a>link with extra attributes target="_blank" rel="noopener noreferrer" that add some security to these outbound links.

LayoutSingleColumn (and other layouts like LayoutSideNavigation) need to understand what the content is about. Therefore, different parts of the page need to be wrapped with specific components - in this case: LayoutWrapperTopbar, LayoutWrapperMain, and LayoutWrapperFooter.

import {
  LayoutSingleColumn,
  LayoutWrapperTopbar,
  LayoutWrapperMain,
  LayoutWrapperFooter,
  Footer,
  NamedLink,
  ExternalLink,
} from '../../components';

After that we are importing two containers:

  • StaticPage: helps in creating static pages
  • TopbarContainer: creates our Topbar component and fetches the data it needs.
import StaticPage from '../../containers/StaticPage/StaticPage';
import TopbarContainer from '../../containers/TopbarContainer/TopbarContainer';

Then we need to import styles and possible other files from current folder. With CSS we are using CSS Modules to tackle possible clashes of different class names.

import css from './SocialMediaPage.module.css';

Then we also import an image which is used later (<img src={image} alt="My first ice cream." />).

import image from './path/to/image.png';

Then after all the imports we are finally getting into phase were we define the component. const SocialMediaPage = props => { return <div></div>} defines a component called SocialMediaPage with content defined in return part. This is a functional component.

Add page schema

In the template above we are using StaticPage component with some attributes:

    <StaticPage
      className={css.root}
      title="Social media"
      schema={{
        "@context": "http://schema.org",
        "@type": "CollectionPage",
        "description": "Description of this page",
        "name": "Social media page",
      }}
    >
  • className is JSX name for class attribute used in plain HTML.
  • title="Social media" creates <title>Social media</title> element to <head> section of the page. (That title is also used in OpenGraph meta tags). You could also add description="This is the description for the social media page"
  • Then we have schema tag that defines some data for search engines in JSON-LD format. Check schema.org for more information. You can also review Google's structured data types to see if one of them fits your use case.

Define component structure

Inside StaticPage component we define layout (LayoutSingleColumn) and add other components inside semantic content wrappers so that the layout is able to understand where to render those blocks.

<LayoutSingleColumn>
  <LayoutWrapperTopbar>
    <TopbarContainer />
  </LayoutWrapperTopbar>
  <LayoutWrapperMain>
    <!-- You will add your embedding widgets here -->
    <div>
      <NamedLink name="LandingPage">Go to home page</NamedLink> or
      <ExternalLink href="https://google.com">
        Go to Google
      </ExternalLink>
    </div>
  </LayoutWrapperMain>
  <LayoutWrapperFooter>
    <Footer />
  </LayoutWrapperFooter>
</LayoutSingleColumn>

And as a final step we need to export the component. export default SocialMediaPage;. See more from babeljs.org

5. Add some styles to the CSS file

Here's an example what your SocialMediaPage.module.css file could look like:

/**
 * Import custom media queries for the new page.
 * FTW-template use route-based code-splitting, every page create their own CSS files.
 * This import ensures that the page and components inside will get correct media queries,
 * when the app is build.
 */
@import '../../styles/customMediaQueries.css';

.root {
  padding: 24px;

  /* Use CSS variable defined in src/styles/marketplaceDefaults.css */
  background-color: var(--marketplaceColor);
}

6. Add a route to the page

As a last step you need to add the newly created static page to the routing. This can be done in src/routeConfiguration.js. (In FTW-product the file is moved to src/routing/routeConfiguration.js.)

Inside routeConfiguration function you should add a URL path, a page name (it should not conflicting with other pages), and the component itself.

Add a new asynchronous import for the page in the beginning of the file with other page imports:

const SocialMediaPage = loadable(() =>
  import(
    /* webpackChunkName: "SocialMediaPage" */ './containers/SocialMediaPage/SocialMediaPage'
  )
);

and after that add the route configuration to your newly created page: (In this example we created social media page so '/socialmedia' would work well as a path.)

{
  path: '/socialmedia',
  name: 'SocialMediaPage',
  component: SocialMediaPage,
},

Read more

We are using several libraries in this example. If you want to read more, here's some pointers:

  • ES2015: imports, exports, arrow functions
  • React: for creating components
  • JSX: for getting HTML-like markup syntax for own components
  • CSS Modules
  • React Router: routing inside the application.