This episode builds Gatsby's visual foundation: creating pages through files in src/pages, separating reusable components with the layout pattern, choosing a styling strategy from CSS Modules to Tailwind, and managing metadata with the Gatsby Head API.

Your Gatsby project is now alive. Time to build a real interface: pages, components, and layouts. The quality of your component architecture at this stage determines how easily the project grows in the coming episodes.
Episode 4 covers creating pages via files in src/pages, reusable layout patterns, three popular styling strategies, and managing page metadata with the Gatsby Head API.
Every file in src/pages becomes a page whose URL follows the file name. Create a new file src/pages/about.jsx:
const AboutPage = () => (
<main>
<h1>Tentang Saya</h1>
<p>Halaman ini tersedia di rute /about/ secara otomatis.</p>
</main>
)
export default AboutPageSave the file and open http://localhost:8000/about — the page is immediately available without any additional routing configuration. That's how Gatsby's file-based routing works.
Notice that a page is just a regular React component. You can use props, state, and every React feature inside it. Gatsby only adds the file-location convention as the route resolver.
Elements like header, nav, and footer are usually the same across all pages. The common pattern: a Layout component that wraps children:
import { Link } from "gatsby"
const Layout = ({ children }) => (
<div>
<header>
<nav>
<Link to="/">Home</Link>
<Link to="/about">Tentang</Link>
</nav>
</header>
<main>{children}</main>
<footer>Hak cipta Gatsby Belajar</footer>
</div>
)
export default LayoutGatsby's Link component gives two advantages: client-side navigation without a full reload and automatic prefetching. This Layout is then used on every page by wrapping the content:
import Layout from "../components/Layout"
const AboutPage = () => (
<Layout>
<h1>Tentang Saya</h1>
</Layout>
)
export default AboutPageCSS Modules provide automatic scoping: class names in a file never conflict with other files. The file name must end with .module.css:
.container {
max-width: 720px;
margin: 0 auto;
}
.heading {
color: rebeccapurple;
}import * as styles from "./styles.module.css"
const AboutPage = () => (
<section className={styles.container}>
<h1 className={styles.heading}>Tentang Saya</h1>
</section>
)import * as styles from "./styles.module.css" gives you an object containing the scoped class names; use them via className={styles.heading}.
For component-based styling, install styled-components together with gatsby-plugin-styled-components so SSR works correctly. For utility-first, Tailwind CSS is also supported through PostCSS — just follow Tailwind's official Gatsby installation guide. All three are valid; pick what your team prefers.
Since Gatsby 4.19, the recommended way to manage page metadata is the Gatsby Head API. Export a Head function from the page file:
const AboutPage = () => <h1>Tentang Saya</h1>
export default AboutPage
export function Head() {
return (
<>
<title>Tentang Saya</title>
<meta name="description" content="Profil singkat penulis" />
</>
)
}The Head function in a page file renders the elements that will be injected into the HTML head section — replacing the react-helmet plugin that used to be the standard, because Head is rendered at build time without runtime overhead.
Because Head is attached to the page, metadata can be arranged per page, and it can even use data from a page query. This matters for SEO: every page has a unique title and description without duplication.
Episode 4 built Gatsby's basic interface: file-based routing, a reusable layout component, three styling approaches, and metadata management with the Gatsby Head API.
Key takeaways:
src/pages automatically becomes a route.Layout component wraps children and is reused on every page.Link provides client-side navigation and prefetching.In the next episode we dive into Gatsby's heart: data fetching and GraphQL — understanding the data layer, distinguishing page queries from static queries, providing content from Markdown and JSON, and querying images and relationships between content.