{
  "demo": true,
  "settings": {
    "merge": {
      "companyName": "grid",
      "tagline": "A fast parallel task runner and build cache for the terminal."
    }
  },
  "data_tables": [
    {
      "key": "contact_submissions",
      "name": "Contact Enquiries",
      "description": "Seeded contact-form submissions for the grid demo. A submission becomes a row here and emails the site admins.",
      "columns": [
        { "key": "name", "label": "Name", "type": "text", "required": true },
        { "key": "email", "label": "Email", "type": "email", "required": true },
        { "key": "project", "label": "Project", "type": "text", "required": false },
        { "key": "message", "label": "Message", "type": "text", "required": true }
      ]
    }
  ],
  "pages": [
    {
      "slug": "/",
      "title": "grid",
      "template_key": "landing",
      "blocks": [
        {
          "block_key": "hero",
          "title": "Hero",
          "slot": "main",
          "sort_order": 1,
          "content": {
            "template": "centered",
            "minHeight": "screen",
            "eyebrow": "v1.4.0",
            "headline": "Run every task in parallel",
            "subheadline": "grid is a task runner and build cache for the terminal.",
            "description": "Define tasks once. grid runs the ones that changed, in parallel, and caches the rest. No config server, no daemon.",
            "ctaPrimary": { "text": "Install", "url": "/contact" },
            "ctaSecondary": { "text": "Read the docs", "url": "/blog" }
          }
        },
        {
          "block_key": "feature-grid",
          "title": "Features",
          "slot": "main",
          "sort_order": 2,
          "content": {
            "eyebrow": "What it does",
            "heading": "One binary, three jobs",
            "intro": "Runs tasks, caches output, and watches files. Nothing else to install.",
            "layout": "card",
            "columns": 3,
            "items": [
              { "icon": "lucide:cpu", "title": "Parallel", "text": "Tasks that do not depend on each other run at the same time, up to your core count." },
              { "icon": "lucide:database", "title": "Cached", "text": "Every task output is keyed by its inputs. Unchanged inputs skip the work." },
              { "icon": "lucide:eye", "title": "Watch", "text": "Point grid at a file glob and it reruns the affected tasks on save." }
            ]
          }
        },
        {
          "block_key": "terminal:code_console",
          "title": "Install",
          "slot": "main",
          "sort_order": 3,
          "content": {
            "prompt": "$",
            "language": "shell",
            "command": "curl -fsSL https://grid.dev/install.sh | sh",
            "output": "installing grid v1.4.0 ...\nok: /usr/local/bin/grid\nrun `grid init` in your project to get started"
          }
        },
        {
          "block_key": "terminal:boot_log",
          "title": "Run log",
          "slot": "main",
          "sort_order": 4,
          "content": {
            "cursor": "block",
            "lines": [
              "grid run build test lint",
              "build   cached   0.00s",
              "lint    ok       0.31s",
              "test    ok       1.12s",
              "3 tasks, 1 cached, 0 failed"
            ]
          }
        },
        {
          "block_key": "cta",
          "title": "CTA",
          "slot": "main",
          "sort_order": 5,
          "content": {
            "background": "band",
            "heading": "Try it on your next build",
            "text": "Install grid, run grid init, and watch your first cached run.",
            "primaryLabel": "Install",
            "primaryUrl": "/contact"
          }
        }
      ]
    },
    {
      "slug": "/about",
      "title": "About grid",
      "template_key": "default",
      "blocks": [
        { "block_key": "heading", "title": "Heading", "slot": "main", "sort_order": 1, "content": { "text": "About grid", "level": 1 } },
        { "block_key": "rich-text", "title": "Story", "slot": "main", "sort_order": 2, "content": { "html": "<p>grid started as a shell script that ran build steps in the background. The script grew until it needed a cache. Then it needed a dependency graph. At that point it became a real tool.</p><p>The goal has not changed. Run the work that changed, skip the work that did not, and stay out of the way. grid is open source and ships as a single static binary.</p>" } },
        {
          "block_key": "terminal:code_console",
          "title": "Quickstart",
          "slot": "main",
          "sort_order": 3,
          "content": { "prompt": "$", "language": "shell", "command": "grid init && grid run build", "output": "wrote grid.toml\nbuild   ok   0.84s\n1 task, 0 cached, 0 failed" }
        },
        {
          "block_key": "terminal:keybind_table",
          "title": "Commands",
          "slot": "main",
          "sort_order": 4,
          "content": {
            "rows": [
              { "keys": "grid run", "action": "Run the named tasks and their dependencies" },
              { "keys": "grid watch", "action": "Rerun affected tasks when files change" },
              { "keys": "grid graph", "action": "Print the task dependency graph" },
              { "keys": "grid clean", "action": "Drop the local build cache" }
            ]
          }
        },
        { "block_key": "divider", "title": "Divider", "slot": "main", "sort_order": 5, "content": { "variant": "line", "weight": "medium" } },
        { "block_key": "quote", "title": "Quote", "slot": "main", "sort_order": 6, "content": { "style": "pull", "quote": "Do the work once. Cache the rest.", "attribution": "grid README" } }
      ]
    },
    {
      "slug": "/blog",
      "title": "Changelog",
      "template_key": "blog-index",
      "blocks": [
        { "block_key": "heading", "title": "Heading", "slot": "main", "sort_order": 1, "content": { "text": "Changelog", "level": 1 } },
        { "block_key": "card", "title": "Post: Cache keys", "slot": "main", "sort_order": 2, "content": { "layout": "vertical", "title": "How grid keys the cache", "text": "<p>Every task output is keyed by its inputs. Here is how the hash is built and why it is stable across machines.</p>", "link": "/blog/cache-keys", "linkLabel": "Read on" } },
        { "block_key": "card", "title": "Post: Watch mode", "slot": "main", "sort_order": 3, "content": { "layout": "vertical", "title": "Watch mode without a daemon", "text": "<p>grid watch reruns affected tasks on save with no background process. This is how the file watcher stays cheap.</p>", "link": "/blog/watch-mode", "linkLabel": "Read on" } },
        { "block_key": "card", "title": "Post: Parallel", "slot": "main", "sort_order": 4, "content": { "layout": "vertical", "title": "Scheduling tasks in parallel", "text": "<p>Independent tasks run together, up to your core count. The scheduler is a topological sort with a worker pool.</p>", "link": "/blog/parallel-scheduling", "linkLabel": "Read on" } }
      ]
    },
    {
      "slug": "/blog/cache-keys",
      "title": "How grid keys the cache",
      "template_key": "article",
      "parent_slug": "/blog",
      "blocks": [
        { "block_key": "terminal:manpage_header", "title": "Man header", "slot": "main", "sort_order": 1, "content": { "name": "CACHE-KEYS", "section": 7, "version": "grid v1.4.0" } },
        { "block_key": "heading", "title": "Title", "slot": "main", "sort_order": 2, "content": { "text": "How grid keys the cache", "level": 1 } },
        { "block_key": "rich-text", "title": "Body", "slot": "main", "sort_order": 3, "content": { "html": "<p>A cache is only useful if the key is exact. grid hashes the task command, its input files, and the tool versions it declares. Same inputs, same key, cached output.</p><p>The key is content based, not time based. Two machines that check out the same commit build the same key. That makes the cache shareable across a team.</p>" } },
        { "block_key": "terminal:code_console", "title": "Example", "slot": "main", "sort_order": 4, "content": { "prompt": "$", "language": "shell", "command": "grid run build --explain", "output": "build key: sha256:9f2c...\ninputs: src/**, grid.toml, go 1.26\nresult: cache hit" } }
      ]
    },
    {
      "slug": "/blog/watch-mode",
      "title": "Watch mode without a daemon",
      "template_key": "article",
      "parent_slug": "/blog",
      "blocks": [
        { "block_key": "terminal:manpage_header", "title": "Man header", "slot": "main", "sort_order": 1, "content": { "name": "WATCH", "section": 1, "version": "grid v1.4.0" } },
        { "block_key": "heading", "title": "Title", "slot": "main", "sort_order": 2, "content": { "text": "Watch mode without a daemon", "level": 1 } },
        { "block_key": "rich-text", "title": "Body", "slot": "main", "sort_order": 3, "content": { "html": "<p>Most watchers run a background process that never exits. grid does not. grid watch runs in the foreground and exits when you press q.</p><p>On each save it maps the changed file back to the tasks that read it, then reruns only those. The rest stay cached.</p>" } },
        { "block_key": "terminal:code_console", "title": "Example", "slot": "main", "sort_order": 4, "content": { "prompt": "$", "language": "shell", "command": "grid watch 'src/**/*.go'", "output": "watching 42 files\nchanged: src/api/handler.go\ntest    ok   0.90s" } }
      ]
    },
    {
      "slug": "/blog/parallel-scheduling",
      "title": "Scheduling tasks in parallel",
      "template_key": "article",
      "parent_slug": "/blog",
      "blocks": [
        { "block_key": "terminal:manpage_header", "title": "Man header", "slot": "main", "sort_order": 1, "content": { "name": "SCHEDULER", "section": 7, "version": "grid v1.4.0" } },
        { "block_key": "heading", "title": "Title", "slot": "main", "sort_order": 2, "content": { "text": "Scheduling tasks in parallel", "level": 1 } },
        { "block_key": "rich-text", "title": "Body", "slot": "main", "sort_order": 3, "content": { "html": "<p>grid builds a graph of tasks and their dependencies. It runs a task the moment its dependencies finish. Independent branches run at the same time.</p><p>The worker pool is sized to your core count by default. You can cap it with a flag when a task is memory heavy.</p>" } },
        { "block_key": "terminal:code_console", "title": "Example", "slot": "main", "sort_order": 4, "content": { "prompt": "$", "language": "shell", "command": "grid run all --jobs 4", "output": "scheduled 9 tasks across 4 workers\nall   ok   2.03s" } }
      ]
    },
    {
      "slug": "/contact",
      "title": "Contact",
      "template_key": "contact",
      "blocks": [
        {
          "block_key": "contact-form",
          "title": "Contact form",
          "slot": "main",
          "sort_order": 1,
          "content": {
            "heading": "Get in touch",
            "description": "Ask a question or report a bug. We reply within one business day.",
            "submitLabel": "Send",
            "successMessage": "Message received. We will reply within one business day.",
            "fields": [
              { "name": "name", "label": "Your name", "type": "text", "required": true, "width": "half" },
              { "name": "email", "label": "Email", "type": "email", "required": true, "width": "half" },
              { "name": "project", "label": "Project", "type": "text", "required": false, "width": "full" },
              { "name": "message", "label": "Message", "type": "textarea", "required": true, "width": "full" }
            ],
            "formConfig": { "enabled": true, "captchaEnabled": false, "targetTable": "contact_submissions" }
          }
        },
        {
          "block_key": "contact-card",
          "title": "Reach us",
          "slot": "main",
          "sort_order": 2,
          "content": {
            "heading": "Other ways in",
            "columns": 3,
            "channels": [
              { "icon": "lucide:mail", "label": "Email", "value": "team@grid.dev", "link": "mailto:team@grid.dev" },
              { "icon": "simple-icons:github", "label": "Source", "value": "github.com/grid-dev/grid", "link": "https://github.com/grid-dev/grid" },
              { "icon": "lucide:message-square", "label": "Chat", "value": "Join the Discord", "link": "#" }
            ]
          }
        }
      ]
    },
    {
      "slug": "/login",
      "title": "Sign in",
      "template_key": "auth",
      "blocks": [
        { "block_key": "auth-form", "title": "Sign in", "slot": "main", "sort_order": 1, "content": { "default_tab": "login", "show_social": false } }
      ]
    }
  ],
  "menu_items": [
    { "menu": "main", "label": "Home", "page_slug": "/", "sort_order": 1 },
    { "menu": "main", "label": "About", "page_slug": "/about", "sort_order": 2 },
    { "menu": "main", "label": "Docs", "page_slug": "/blog", "sort_order": 3 },
    { "menu": "main", "label": "Contact", "page_slug": "/contact", "sort_order": 4 }
  ]
}
