{ "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": "
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.
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.
" } }, { "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": "Every task output is keyed by its inputs. Here is how the hash is built and why it is stable across machines.
", "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": "grid watch reruns affected tasks on save with no background process. This is how the file watcher stays cheap.
", "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": "Independent tasks run together, up to your core count. The scheduler is a topological sort with a worker pool.
", "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": "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.
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.
" } }, { "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": "Most watchers run a background process that never exits. grid does not. grid watch runs in the foreground and exits when you press q.
On each save it maps the changed file back to the tasks that read it, then reruns only those. The rest stay cached.
" } }, { "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": "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.
The worker pool is sized to your core count by default. You can cap it with a flag when a task is memory heavy.
" } }, { "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 } ] }