Configuration

Detailed reference for site.json, navigation.json, contentTypes.json, and eleventy.config.js.

Overview

Ink's configuration is split across four files, each with a specific purpose. All data files live in src/_data/ and are available in every template as global variables.

site.json

The primary site metadata file. Every field here is accessible in templates via site.fieldName.

{
  "name": "My Business",
  "tagline": "We build great websites",
  "url": "https://mybusiness.com",
  "description": "A short description for search engines and social cards.",
  "email": "hello@mybusiness.com",
  "phone": "(555) 123-4567",
  "address": {
    "street": "123 Main St",
    "city": "Austin",
    "state": "TX",
    "zip": "78701"
  },
  "social": {
    "twitter": "https://twitter.com/mybusiness",
    "facebook": "https://facebook.com/mybusiness",
    "linkedin": "https://linkedin.com/company/mybusiness",
    "instagram": "https://instagram.com/mybusiness"
  },
  "gtm_id": "GTM-XXXXXXX"
}

Field Reference

Field Type Description
name string Site/business name, shown in header and title tags
tagline string Short slogan displayed in the header or hero
url string Production URL (used for sitemaps, canonical tags, OG meta)
description string Default meta description for pages without their own
email string Contact email displayed in footer and contact page
phone string Contact phone number
address object Physical address with street, city, state, zip
social object Social media profile URLs
gtm_id string Google Tag Manager container ID (leave empty to disable)

Use these values in templates:

<title>{{ title }} | {{ site.name }}</title>
<meta name="description" content="{{ excerpt or site.description }}">
<a href="mailto:{{ site.email }}">{{ site.email }}</a>

navigation.json

Controls the site's navigation menus. The main array defines the primary navigation links.

{
  "main": [
    { "label": "Home", "url": "/" },
    { "label": "Services", "url": "/services/" },
    { "label": "About", "url": "/about/" },
    {
      "label": "Resources",
      "url": "/resources/",
      "children": [
        { "label": "Blog", "url": "/blog/" },
        { "label": "FAQ", "url": "/faq/" },
        { "label": "Docs", "url": "/docs/" }
      ]
    },
    { "label": "Contact", "url": "/contact/" }
  ]
}

Dropdown Menus

Any navigation item with a children array renders as a dropdown menu. Each child has the same label and url structure. The parent url is used as a fallback link for accessibility.

Using Navigation in Templates

Navigation data is available as navigation.main:

<nav>
  <ul>
    {% for item in navigation.main %}
      <li>
        <a href="{{ item.url }}">{{ item.label }}</a>
        {% if item.children %}
          <ul class="dropdown">
            {% for child in item.children %}
              <li><a href="{{ child.url }}">{{ child.label }}</a></li>
            {% endfor %}
          </ul>
        {% endif %}
      </li>
    {% endfor %}
  </ul>
</nav>

contentTypes.json

The collection factory configuration. Each key is an Eleventy tag name, and the value specifies which files to collect and how to sort them.

{
  "posts": {
    "glob": "content/blog/*.md",
    "sort": "date"
  },
  "services": {
    "glob": "content/services/*.md",
    "sort": "order"
  },
  "employees": {
    "glob": "content/employees/*.md",
    "sort": "order"
  },
  "docs": {
    "glob": "content/docs/*.md",
    "sort": "order"
  }
}

Field Reference

Field Type Description
glob string File path pattern relative to the project root
sort string "date" for reverse-chronological or "order" for numeric frontmatter field

When sort is "date", entries are sorted newest-first using the date frontmatter field. When sort is "order", entries are sorted by the numeric order field in ascending order.

You should not need to edit this file manually. The ink add and ink remove commands manage it for you. However, understanding its structure is useful when creating custom integrations.

eleventy.config.js

The main Eleventy configuration file at the project root. Ink's config handles several things:

import contentTypes from "./src/_data/contentTypes.json" with { type: "json" };

export default function(eleventyConfig) {
  // Passthrough copy: static assets served as-is
  eleventyConfig.addPassthroughCopy("public");
  eleventyConfig.addPassthroughCopy("media");

  // Collection factory: creates a collection for each content type
  for (const [tag, config] of Object.entries(contentTypes)) {
    eleventyConfig.addCollection(tag, (collectionApi) => {
      const items = collectionApi.getFilteredByGlob(config.glob);
      if (config.sort === "date") {
        return items.sort((a, b) => b.date - a.date);
      }
      return items.sort((a, b) =>
        (a.data.order || 0) - (b.data.order || 0)
      );
    });
  }

  return {
    dir: {
      input: ".",
      includes: "src/_includes",
      layouts: "src/_layouts",
      data: "src/_data",
      output: "_site"
    },
    markdownTemplateEngine: "njk",
    htmlTemplateEngine: "njk"
  };
};

Key Configuration Options

Option Value Description
dir.input "." Project root is the input directory (content/ at root level)
dir.includes "src/_includes" Partials and components
dir.layouts "src/_layouts" Page layouts
dir.data "src/_data" Global data files
dir.output "_site" Build output directory
markdownTemplateEngine "njk" Process Markdown files through Nunjucks first
htmlTemplateEngine "njk" Process HTML files through Nunjucks

Passthrough Copies

The addPassthroughCopy calls tell Eleventy to copy files directly to the output without processing. The public/ directory holds static assets like favicons, _headers, and _redirects. The media/ directory holds images.

Adding Custom Filters

You can add Nunjucks filters in eleventy.config.js:

eleventyConfig.addFilter("readableDate", (date) => {
  return new Date(date).toLocaleDateString("en-US", {
    year: "numeric",
    month: "long",
    day: "numeric"
  });
});

Then use it in templates:

<time>{{ post.date | readableDate }}</time>