Basker Docs

Build the default layout

Assemble the HTML shell every page shares: head metadata, Open Graph tags, body classes, and the components that wrap your content

A layout is the outer HTML every template renders into. Your theme needs at least one, layouts/default.liquid. This is where the parts that should appear on every page live: the <head>, global stylesheets, headers, and footers.

You will build it in stages.

Step 1: Create the file

Create layouts/default.liquid. Start with a doctype and an empty shell:

<!DOCTYPE html>
<html lang="en">
  <head>
  </head>
  <body>
  </body>
</html>

Save the file. The dev-server browser tab should reload to a blank-but-valid page.

Step 2: Add the page metadata

The renderer exposes a handful of globals that resolve to the right values for the page a visitor views. These include page_title, page_description, page_image, and body_classes. Use them in the <head> so every page gets its own title, social share image, and meta description without extra per-page code.

Add this to the <head>:

<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ page_title }}: Remarkable Theatre</title>

<meta name="description" content="{{ page_description }}">
<meta property="og:title" content="{{ page_title }}">
<meta property="og:description" content="{{ page_description }}">
<meta property="og:image" content="{{ page_image }}">

Replace Remarkable Theatre with your site's name, or connect it to a setting later. You will add a site.name setting on the Variants and theme settings page.

Step 3: Make space for header injections

Basker injects JSON-LD, the preview banner, generator meta, and similar head-level content via {{ content_for_header }}. Add it after your page metadata and before your stylesheets:

{{ content_for_header }}

Without this tag, structured data will not render. The preview banner will also not show when you preview draft content.

Create a flat assets/main.css for now:

touch assets/main.css

Reference it from the layout using the asset_url filter. The stylesheet_tag filter wraps the URL in a <link> element with the right attributes:

{{ 'main.css' | asset_url | stylesheet_tag }}

Add that line after {{ content_for_header }}.

The path you pass to asset_url is relative to your assets/ folder. Nested layouts work too ('css/main.css'), but for the tutorial, keep things flat. A flat structure is easier to debug, and Basker's CDN does not care either way.

Step 5: Add the body classes

Add a body_classes variable to the opening tag. A base template produces page. Named template parts add classes such as page-featured. These give you useful variant-specific CSS hooks.

<body class="{{ body_classes }}">
</body>

Most themes split their global UI into reusable components and use {% render %} to include them. Create two files:

components/global-header.liquid:

<header class="site-header">
  <a href="/" class="site-header__logo">Remarkable Theatre</a>
  <nav class="site-header__nav">
    <a href="/about">About</a>
    <a href="/events">What's on</a>
    <a href="/contact">Contact</a>
  </nav>
</header>

components/global-footer.liquid:

<footer class="site-footer">
  <p>&copy; {{ 'now' | date: '%Y' }} Remarkable Theatre</p>
</footer>

Then render them from the layout, with the page content placed between them:

<body class="{{ body_classes }}">
  {% render 'components/global-header' %}

  <main class="page">
    {{ content_for_layout }}
  </main>

  {% render 'components/global-footer' %}
</body>

{{ content_for_layout }} is where the rendered template body lands. Without it, only the layout's own markup would show.

The {% render %} tag resolves both components/ and snippets/ paths. The path prefix tells the renderer which folder to look in. The convention uses components/ for larger page-level parts, such as the header, footer, and navigation. It uses snippets/ for smaller reusable parts, such as icons and formatters. Use whichever fits the piece you build.

Step 7: Final layout

Your layouts/default.liquid should now look like this:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>{{ page_title }}: Remarkable Theatre</title>

    <meta name="description" content="{{ page_description }}">
    <meta property="og:title" content="{{ page_title }}">
    <meta property="og:description" content="{{ page_description }}">
    <meta property="og:image" content="{{ page_image }}">

    {{ content_for_header }}
    {{ 'main.css' | asset_url | stylesheet_tag }}
  </head>
  <body class="{{ body_classes }}">
    {% render 'components/global-header' %}

    <main class="page">
      {{ content_for_layout }}
    </main>

    {% render 'components/global-footer' %}
  </body>
</html>

What's next

The layout is ready, but {{ content_for_layout }} is empty until you add a template that writes into it. That is the next page: Add page templates.

Going deeper

  • Layouts: alternate layouts, {% layout %} overrides, validation rules.
  • Liquid tags: full reference for render, asset_url, stylesheet_tag, and the rest.
  • Template context: every global available in a layout or template.

On this page