One to Zero: How to build a static website using a zero configuration toolkit

General purpose tools usually require complex configuration which, more often than not, can be a huge pain. If you’ve ever tried setting up something like Webpack, you probably can relate to that sentiment. Introducing zero-configuration toolkits, a new wave of toolkits that promises to make life easier for deploying your projects, such as static websites.

In this article, we’ll introduce you to x0, a zero-configuration toolkit for React development of static sites, and show how you can create a static website using zero-config toolkit stack of x0 paired with Contentful for content infrastructure and Netlify which hosts static websites.

Check out an example of a static website that supports real-time data and download the files we’ll be working with in this article.

What is zero config toolkit?

The main way to reduce process repetition and complexity when deploying a static website is to have as few dependencies as possible, ideally just one, to start shipping the product to production.

Zero-configuration enables that with a toolkit that works without configuration in common use cases and provides extensibility to cover additional use cases. The advantages over the traditional way of deploying websites are:

  • Zero-config toolkits are continuously updated.
  • The toolkit automatically keeps its own dependencies up-to-date.
  • The absence of an application-side config allows seamless updates without code changes on the app side.

Why Static Sites?

Static websites are a great fit for use cases like landing pages which don’t require any real-time data. You’d want to use a static website because they are:

  • Fast. The final assets are just HTML, CSS, and Javascript, making the site as light as it can be.
  • Low-maintenance and low cost. There is no need for a server since all the content is embedded directly in the HTML and, with Contentful, hosting is provided via Netlify.
  • Made for SEO. Crawlers can parse content from the page’s source code.

The only downside is, as mentioned, that you lose the ability to have real-time data. We do have a solution to address content updates; that is to trigger a CI build script using webhook from Contentful.

Getting your website started with x0

x0 has built-in support of React, React-router and various CSS-in-JS libraries. Here’s a rundown of the relatively straightforward 5-step process to deploying your website using x0:

  • Install x0
  • Add pages
  • Style your components
  • Data fetching and management
  • Deploying the site using Netlify

1. Installing x0

Start by using installing the toolkit:

$ npm install @compositor/x0 --save

$ mkdir src && touch src/App.js

While npm is doing its thing, use the time to sign up for a free Contentful account — you can make it even easier and sign in using your Github account with one click.

Let's create a simple page using x0 via the file src/App.js and the following code:

1
2
3
4
5
6
7
import React from 'react';
const App = props => (
  <div>
    <h1>Static site built with Contentful and x0!</h1>
  </div>
);
export default App;

Using the following command, you can build the website by getting x0 to compile it to the dist folder:

$ x0 build src/App.js --out-dir dist --static

2. Multi pages

Now to add a couple of new pages — since react-router is supported out of the box, let's use it:

$ npm i react-router-dom --save

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import React from 'react';
import { BrowserRouter, StaticRouter, Route, Link } from 'react-router-dom';
import Home from './Home';
import Categories from './Categories';
import Courses from './Courses';
const Router = typeof document !== 'undefined' ? BrowserRouter : StaticRouter;
const App = props => (
  <Router location={props.pathname} context={{}}>
    <React.Fragment>
      <nav>
        <Link to="/">Home</Link>
        <Link to="/categories">Categories</Link>
        <Link to="/courses">Courses</Link>
      </nav>
      <Route exact path="/" render={() => <Home {...props} />} />
      <Route
        path="/categories"
        render={() => <Categories {...props} />}
      />
      <Route
        path="/courses"
        render={() => <Courses {...props} />}
      />
    </React.Fragment>
  </Router>
);

Next, we need to provide a list of pages to x0 — which reads the following section in package.json:

1
2
3
4
5
6
7
8
9
10
{
  ...
  "x0": {
    "routes": [
      "/",
      "/categories",
      "/courses"
    ]
  }
}

3. Styling

x0 supports styled components, and isn’t limited to just the native styled-components API. In fact, it can also be used with any framework built on top of styled-components such as Rebass.

As an example on how to style, the following lines style the links on your website with some color:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import React from 'react';
import { NavLink } from 'react-router-dom';
import styled from 'styled-components';
const NavItem = styled(NavLink)`
  display: inline-block;
  color: red;
  margin-right: 20px;
  margin-bottom: 20px;
  &.active {
    color: green;
    font-size: 1.2em;
  }
`;
export default NavItem;

4. Data fetching and management

x0 supports asynchronous data fetching using the getInitialProps hook. This was inspired by next.js and has just one limitation: for now, it's only supported at the top level and cannot be used in child components.

This example uses Contentful as the data provider.

1
2
3
4
5
6
7
8
9
10
11
12
import { createClient } from 'contentful';
const client = createClient({
  accessToken: '6f7ec47bfe1a38705c7f5b8852e2df4ff9d772ea42cfe06348ea4d6f4b6764c7',
  space: 'iegfjg6q47xl'
});
...
App.getInitialProps = async ({ Component, pathname }) => {
  const { items: entries } = await client.getEntries();
  const courses = entries.filter(entry => entry.sys.contentType.sys.id === 'course');
  const categories = entries.filter(entry => entry.sys.contentType.sys.id === 'category');
  return { courses, categories };
};

5. Using Netlify to deploy the website

And finally, we’re ready to get our website online for the world to see. We’re going to do this via Netlify so we need to install that first:

$ brew tap netlify/netlifyctl

$ brew install netlifyctl

Log in to Netlify using:

$ netlifyctl login

And finally, deploy the static website using the following command:

$ netlifyctl deploy -b dist

Alternatively, you can link your repository with Netlify, where you would also need to specify the build script and a folder to deploy from the web interface

Link your repository with Netlify

6. Closing the circle: webhook from Contentful to Netlify

A webhook is a way for an app to provide other applications with real-time information. This section is where the magic of adding real-time updates to your static website happens.

Using webhoooks for real-time updates

Contentful allows creating an outgoing webhook to notify application consumer that the data was updated.

Configuring your webhook

This way, the static website will be rebuilt each time modifications happen from you changing content on Contentful's side.

x0 Toolkit is still Configurable

It's called a zero-config toolkit, but if you still want to configure things, x0 doesn't compromise on that and supports extensibility by using custom webpack configs. Let's learn how to add a TypeScript module like a custom webpack configuration with the TypeScript loader.

Bring up the TypeScript loader:

$ npm install --save-dev typescript awesome-typescript-loader @types/react @types/react-dom

…and with the following lines in webpack.config.js:

1
2
3
4
5
6
7
8
9
10
module.exports = {
  resolve: {
    extensions: ['.tsx', '.js']
  },
  module: {
    rules: [
      { test: /\.tsx$/, loader: 'awesome-typescript-loader' }
    ]
  }
}

We can now proceed to use a custom configuration with x0.

--config webpack.config.js

Now we have types checking powered by TS with almost no additional code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import * as React from 'react';
import { Entry } from 'contentful';
interface Course {
  title: string;
};
const Courses: React.SFC<{ courses: Entry<Course>[] }> = ({ courses }) => {
  return (
    <div>
      <h1>Courses</h1>
      <ul>
        {courses.map(course => (
          <li key={course.sys.id}>{course.fields.title}</li>
        ))}
      </ul>
    </div>
  );
};
export default Courses;

Conclusion

x0 can help hasten the development and launch of landing pages by allowing developers to concentrate on code. We learned how using zero-config toolkits helps to reduce time-to-production by eliminating the costs of creating and maintaining various configurations.

So go ahead and create that free Contentful account and get your zero-config static site online, or try out the many other wonderful ways Contentful's content infrastructure can help support you and your web projects.

Blog posts in your inbox

Subscribe to receive most important updates. We send emails once a month.