{
  "version": "https://jsonfeed.org/version/1",
  "title": "Marmite 0.4.0",
  "home_page_url": "https://marmite.blog",
  "feed_url": "https://marmite.blog/tag-workspace.json",
  "description": "Static Site Generator <br> <small>for blogs</small> <br> <small>made with ❤️ and 🦀</small>",
  "items": [
    {
      "id": "https://marmite.blog/workspace-multi-site-support.html",
      "url": "https://marmite.blog/workspace-multi-site-support.html",
      "title": "Workspace - Multi-Site Support",
      "content_html": "<p>Marmite now supports <strong>workspaces</strong> - a way to manage multiple independent sites from a single project directory and build them all with one command.</p>\n<h2><a href=\"#project-structure\" aria-hidden=\"true\" class=\"anchor\" id=\"project-structure\"></a>Project Structure</h2>\n<p>A workspace is a directory containing multiple marmite sites, identified by a <code>marmite-workspace.yaml</code> file at the root:</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner\">myproject/\n  blog/\n    content/\n    marmite.yaml\n  photos/\n    content/\n    marmite.yaml\n  marmite-workspace.yaml\n</code></pre>\n<p>Each subfolder (<code>blog/</code>, <code>photos/</code>) is a regular marmite site that can also be built independently with <code>marmite myproject/blog output</code>.</p>\n<h2><a href=\"#workspace-configuration\" aria-hidden=\"true\" class=\"anchor\" id=\"workspace-configuration\"></a>Workspace Configuration</h2>\n<p>Create a <code>marmite-workspace.yaml</code> at the project root:</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner language-yaml\"><a-c># List of sites in build order (required)</a-c>\n<a-pr>sites</a-pr><a-p>:</a-p>\n  <a-p>-</a-p> <a-pr>name</a-pr><a-p>:</a-p> <a-s>blog</a-s>\n  <a-p>-</a-p> <a-pr>name</a-pr><a-p>:</a-p> <a-s>photos</a-s>\n\n<a-c># Which site serves at &quot;/&quot; (default: first in list)</a-c>\n<a-pr>default_site</a-pr><a-p>:</a-p> <a-s>blog</a-s>\n\n<a-c># If true, root &quot;/&quot; gets a redirect instead of the default site content</a-c>\n<a-pr>redirect</a-pr><a-p>:</a-p> <a-co>false</a-co>\n\n<a-c># Shared configuration defaults inherited by all sites</a-c>\n<a-pr>defaults</a-pr><a-p>:</a-p>\n  <a-pr>language</a-pr><a-p>:</a-p> <a-s>en</a-s>\n  <a-pr>pagination</a-pr><a-p>:</a-p> <a-n>10</a-n>\n  <a-pr>enable_search</a-pr><a-p>:</a-p> <a-co>true</a-co>\n\n<a-c># Separator for cross-site references (default: &quot;::&quot;)</a-c>\n<a-pr>separator</a-pr><a-p>:</a-p> <a-s>&quot;::&quot;</a-s></code></pre>\n<h3><a href=\"#site-entry-options\" aria-hidden=\"true\" class=\"anchor\" id=\"site-entry-options\"></a>Site Entry Options</h3>\n<p>Each entry in <code>sites</code> accepts:</p>\n<ul>\n<li><code>name</code> (required) - the directory name</li>\n<li><code>output_path</code> (optional) - custom output subdirectory name, defaults to the directory name</li>\n</ul>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner language-yaml\"><a-pr>sites</a-pr><a-p>:</a-p>\n  <a-p>-</a-p> <a-pr>name</a-pr><a-p>:</a-p> <a-s>blog</a-s>\n    <a-pr>output_path</a-pr><a-p>:</a-p> <a-s>b</a-s>    <a-c># renders to output/b/ instead of output/blog/</a-c>\n  <a-p>-</a-p> <a-pr>name</a-pr><a-p>:</a-p> <a-s>photos</a-s></code></pre>\n<h2><a href=\"#building-a-workspace\" aria-hidden=\"true\" class=\"anchor\" id=\"building-a-workspace\"></a>Building a Workspace</h2>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner language-console\">$ marmite myproject output -v\nWorkspace mode: 2 site(s) detected\nBuilding site 'blog' -&gt; output\nBuilding site 'photos' -&gt; output/photos\nWorkspace generated at: output/\n</code></pre>\n<p>The default site renders directly at the output root. Other sites render to subdirectories.</p>\n<h2><a href=\"#root-site-behavior\" aria-hidden=\"true\" class=\"anchor\" id=\"root-site-behavior\"></a>Root Site Behavior</h2>\n<p>By default, the first site (or the one specified by <code>default_site</code>) renders at the root of the output directory. Other sites render as subdirectories.</p>\n<p>With <code>redirect: true</code>, all sites render to their own subdirectories and the root <code>index.html</code> is a meta-refresh redirect to the default site:</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner language-yaml\"><a-pr>default_site</a-pr><a-p>:</a-p> <a-s>blog</a-s>\n<a-pr>redirect</a-pr><a-p>:</a-p> <a-co>true</a-co></code></pre>\n<p>This generates <code>output/blog/</code>, <code>output/photos/</code>, and an <code>output/index.html</code> that redirects to <code>/blog/</code>.</p>\n<h2><a href=\"#configuration-inheritance\" aria-hidden=\"true\" class=\"anchor\" id=\"configuration-inheritance\"></a>Configuration Inheritance</h2>\n<p>The <code>defaults</code> section in <code>marmite-workspace.yaml</code> provides base configuration values for all sites. Each site's own <code>marmite.yaml</code> overrides these defaults. Fields not specified in the site config inherit from the workspace defaults.</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner language-yaml\"><a-c># marmite-workspace.yaml</a-c>\n<a-pr>defaults</a-pr><a-p>:</a-p>\n  <a-pr>language</a-pr><a-p>:</a-p> <a-s>en</a-s>\n  <a-pr>pagination</a-pr><a-p>:</a-p> <a-n>10</a-n>\n  <a-pr>enable_search</a-pr><a-p>:</a-p> <a-co>true</a-co>\n\n<a-c># blog/marmite.yaml - overrides name but inherits everything else</a-c>\n<a-pr>name</a-pr><a-p>:</a-p> <a-s>My Blog</a-s>\n<a-pr>tagline</a-pr><a-p>:</a-p> <a-s>A personal blog</a-s></code></pre>\n<p>CLI-passed configuration flags (like <code>--pagination 5</code>) apply only to the workspace-level defaults, not to values explicitly set in individual site configs.</p>\n<h2><a href=\"#cross-site-references\" aria-hidden=\"true\" class=\"anchor\" id=\"cross-site-references\"></a>Cross-Site References</h2>\n<p>Sites in a workspace can link to each other using the <code>::</code> separator (configurable via <code>separator</code> in the workspace config):</p>\n<h3><a href=\"#links\" aria-hidden=\"true\" class=\"anchor\" id=\"links\"></a>Links</h3>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner language-markdown\">Check out the [photo gallery](photos::gallery.html).</code></pre>\n<p>This renders as a link to <code>/photos/gallery.html</code>.</p>\n<h3><a href=\"#media\" aria-hidden=\"true\" class=\"anchor\" id=\"media\"></a>Media</h3>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner language-markdown\">![Banner](photos::media/sunset.jpg)</code></pre>\n<p>This renders as an image source pointing to <code>/photos/media/sunset.jpg</code>.</p>\n<h3><a href=\"#shortcodes\" aria-hidden=\"true\" class=\"anchor\" id=\"shortcodes\"></a>Shortcodes</h3>\n<p>Content-gathering shortcodes accept a <code>site</code> parameter to pull content from other sites in the workspace:</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner language-markdown\"><a-c>&lt;!-- .posts site=&quot;photos&quot; --&gt;</a-c>\n<a-c>&lt;!-- .tags site=&quot;blog,photos&quot; --&gt;</a-c>\n<a-c>&lt;!-- .authors site=&quot;all&quot; --&gt;</a-c>\n<a-c>&lt;!-- .pages site=&quot;photos&quot; --&gt;</a-c>\n<a-c>&lt;!-- .streams site=&quot;photos&quot; --&gt;</a-c>\n<a-c>&lt;!-- .series site=&quot;blog&quot; --&gt;</a-c></code></pre>\n<p>The <code>site</code> parameter accepts:</p>\n<ul>\n<li>A single site name: <code>site=&quot;photos&quot;</code> - content from that site only</li>\n<li>A comma-separated list: <code>site=&quot;blog,photos&quot;</code> - merged content from listed sites</li>\n<li>The keyword <code>all</code>: <code>site=&quot;all&quot;</code> - content from every site in the workspace</li>\n</ul>\n<p>Posts and pages returned from other sites have their slugs prefixed with the site's output path, so links generated by <code>url_for</code> point to the correct location (e.g., <code>/photos/first-photo.html</code>).</p>\n<p>The <code>card</code> shortcode also supports cross-site slugs using the <code>::</code> separator or the <code>site</code> parameter:</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner language-markdown\"><a-c>&lt;!-- .card slug=&quot;photos::first-photo&quot; --&gt;</a-c>\n<a-c>&lt;!-- .card slug=&quot;first-photo&quot; site=&quot;photos&quot; --&gt;</a-c></code></pre>\n<p>When no <code>site</code> parameter is provided, shortcodes behave exactly as in single-site mode - showing only the current site's content.</p>\n<h2><a href=\"#cli-commands-in-workspace-mode\" aria-hidden=\"true\" class=\"anchor\" id=\"cli-commands-in-workspace-mode\"></a>CLI Commands in Workspace Mode</h2>\n<p>Most commands work with workspaces:</p>\n<h3><a href=\"#creating-content\" aria-hidden=\"true\" class=\"anchor\" id=\"creating-content\"></a>Creating Content</h3>\n<p>Use <code>--site</code> to specify which site to create content in:</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner language-console\">$ marmite myproject --new &quot;My Post&quot; --site blog\n</code></pre>\n<p>Without <code>--site</code>, workspace mode will prompt you to specify the target site.</p>\n<h3><a href=\"#show-urls\" aria-hidden=\"true\" class=\"anchor\" id=\"show-urls\"></a>Show URLs</h3>\n<p>Aggregates URLs from all sites:</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner language-console\">$ marmite myproject --show-urls\n</code></pre>\n<p>Output is grouped by site name with prefixed paths.</p>\n<h3><a href=\"#shortcodes-1\" aria-hidden=\"true\" class=\"anchor\" id=\"shortcodes-1\"></a>Shortcodes</h3>\n<p>Lists shortcodes from all sites:</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner language-console\">$ marmite myproject --shortcodes\n</code></pre>\n<h3><a href=\"#unsupported-commands\" aria-hidden=\"true\" class=\"anchor\" id=\"unsupported-commands\"></a>Unsupported Commands</h3>\n<p>Theme commands (<code>--init-templates</code>, <code>--start-theme</code>, <code>--set-theme</code>) and <code>--init-site</code> are not supported in workspace mode. Run them on individual sites instead:</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner language-console\">$ marmite myproject/blog --set-theme my-theme\n</code></pre>\n<h2><a href=\"#watch-mode-and-live-reload\" aria-hidden=\"true\" class=\"anchor\" id=\"watch-mode-and-live-reload\"></a>Watch Mode and Live Reload</h2>\n<p>Workspace watch mode monitors all site directories and the workspace config file. Any change triggers a full workspace rebuild with live reload:</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner language-console\">$ marmite myproject output --serve --watch\n</code></pre>\n<p>The built-in server serves the combined output directory, so <code>localhost:8000/</code> shows the default site and <code>localhost:8000/photos/</code> shows the photos site.</p>\n<h2><a href=\"#output-structure\" aria-hidden=\"true\" class=\"anchor\" id=\"output-structure\"></a>Output Structure</h2>\n<p>A <code>sites.json</code> file is generated at the output root listing all sites:</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner language-json\">[\n  {<a-s>&quot;name&quot;</a-s>: <a-s>&quot;blog&quot;</a-s>, <a-s>&quot;path&quot;</a-s>: <a-s>&quot;/blog/&quot;</a-s>},\n  {<a-s>&quot;name&quot;</a-s>: <a-s>&quot;photos&quot;</a-s>, <a-s>&quot;path&quot;</a-s>: <a-s>&quot;/photos/&quot;</a-s>}\n]</code></pre>\n<p>Each site gets its own complete output with static assets, media, feeds, sitemap, and search index.</p>\n<h2><a href=\"#independent-site-builds\" aria-hidden=\"true\" class=\"anchor\" id=\"independent-site-builds\"></a>Independent Site Builds</h2>\n<p>Each subfolder remains a fully independent marmite site. You can always build a single site directly:</p>\n<pre class=\"marmite-code\"><code class=\"marmite-code-inner language-console\">$ marmite myproject/blog output/blog\n</code></pre>\n<p>The workspace feature is purely additive - existing single-site functionality is completely unaffected.</p>\n<blockquote>\n<p>Please consider giving a ☆ on Marmite <a href=\"https://github.com/rochacbruno/marmite\">Github</a> repository, that helps a lot!</p>\n</blockquote>\n<!-- Contents from _markdown_footer.md are appended to every content -->\n<!-- _references.md is a file to gather all references together \nthis file is appended to every raw markdown.\n-->\n",
      "summary": "\"Build and manage multiple marmite sites from a single workspace with cross-site references, shared configuration, and unified builds.\"",
      "date_published": "2026-07-03T15:00:00-00:00",
      "image": "media/workspace-multi-site-support.banner.jpg",
      "authors": [
        {
          "name": "Bruno Rocha",
          "url": "https://go.rocha.social/@bruno",
          "avatar": "https://github.com/rochacbruno.png"
        }
      ],
      "tags": [
        "docs",
        "workspace",
        "multi-site",
        "features"
      ],
      "language": "en"
    }
  ]
}