Guides
Itsy Guides

Pages, layouts and data

Create pages, share markup, and bring JSON data into your HTML.

Pages and URLs

Itsy turns the HTML files in site/ into pages. The file's location determines its URL, so there are no routes to register. The homepage uses index.html, and other page URLs leave off the file extension:

Project filesPublic URL
  • site/
    • index.html/
    • visit.html/visit
    • books/
      • index.html/books
    • images/
      • shop.jpg/images/shop.jpg

Assets keep their file extensions. An image at site/images/shop.jpg is available at /images/shop.jpg. Files beginning with an underscore are private templates, such as the partials described below.

Link to /visit, without .html or a trailing slash. For a page with related files, you can use a folder: site/books/index.html becomes /books. Choose either books.html or books/index.html for that URL; do not create both.

Layouts

site/main.layout.html supplies the document around each page. Put the shared header, navigation, and footer here so you can update them in one place. Itsy inserts the requested page at {slot}:

<header>Little Bookshop</header>
<main>{slot}</main>
<footer>Independent books. Curious readers.</footer>

This illustrates the shared pieces. When editing the generated layout, keep its HTML document and shared navigation. Blog’s admin templates retain their own authentication and CSRF controls.

A page uses main.layout.html automatically. If part of your site needs a different wrapper, create site/shop.layout.html with its own {slot}. Select it with a page settings comment before any markup:

<!-- itsy
layout: /shop.layout.html
-->

Partials

Use a partial for a piece of HTML that appears in more than one place, such as opening hours or a newsletter sign-up link. Save it in an underscore-prefixed file, such as site/_hours.html. Include it in a page or layout with:

{render hours}

The render name leaves off the underscore and .html. Itsy looks beside the template containing the instruction, so {render hours} in a root-level page includes site/_hours.html. For a partial in another folder, use a path from the site root: {render /shared/hours} includes site/shared/_hours.html.

Settings and JSON data

Settings used across the site live under app in itsy.config.json. For example, {app.site_name} displays the site name in a page, layout, or partial. Keep these settings for public information such as your business name or phone number; credentials belong outside this file.

When several items share the same structure, a JSON file lets you manage their content together. Save it in itsy/data/; the filename becomes the name you use in a template. For example, create itsy/data/books.json:

{
  "items": [
    {"title": "A Field Guide to Birds"},
    {"title": "The Quiet Garden"}
  ]
}

The file is available as data.books. Loop over its items in a page or partial; each item is called book inside the loop:

{#each data.books.items as book}
  <p>{book.title}</p>
{:else}
  <p>New books are on their way.</p>
{/each}

Use conditions to show content when a value is present:

{#if app.phone}
  <a href="tel:{app.phone}">{app.phone}</a>
{/if}

{#unless app.phone} does the opposite. Conditions use values such as app.phone, rather than JavaScript expressions.

Page titles and descriptions

The page title is used in the browser tab, while the description gives search engines a summary of the page. Each page can have its own values, separate from its visible heading and body text.

This settings syntax requires Itsy 0.22.0 or newer and server protocol 30.

Put each page's title and description in one leading settings comment, before any markup. If the page uses a custom layout, include that setting in the same comment:

<!-- itsy
title: Visit the bookshop
description: Find our opening hours and plan a visit to Little Bookshop.
layout: /shop.layout.html
-->
<h1>Visit us</h1>

layout is optional; omit it to use main.layout.html. Each value is single-line plain text. Use one settings comment per page; duplicate or unknown keys fail validation.

The layout reads these values with {page.title} and {page.description}. For example, inside the layout's <head>:

<title>{page.title} | {app.site_name}</title>
<meta name="description" content="{page.description}">

Missing or empty titles fall back to Home for the homepage or a title derived from the last part of the URL. Missing or empty descriptions stay empty. Values are escaped for their HTML context; quotes, ampersands, and template braces remain text rather than becoming markup or template instructions.

Keep page copy in HTML and structured lists in JSON data. Blog posts use their title and excerpt for metadata.