This experiment turns a non-Markdown JSON Canvas file into a first-class page. The sandbox tour contains positioned text, groups, file references and an external link, with edges describing the isolation boundary and build pipeline. The .canvas fixture is content consumed by the Canvas page plugin; the explanatory Markdown page is a separate page, not the Canvas renderer’s output.

Exact configuration from /home/loca/dev/quartz-sandbox/sandbox/engine/quartz.config.yaml, lines 162–169:

  - source: "@quartz-community/canvas-page"
    enabled: true
    options:
      enableInteraction: true
      initialZoom: 0.55
      minZoom: 0.1
      maxZoom: 4
    order: 50

The page-type layout override below is another contiguous excerpt from the same file, lines 399–403, nested under layout.byPageType. It excludes the table of contents and clears the right-hand position for Canvas pages.

    canvas:
      exclude:
        - table-of-contents
      positions:
        right: []

Actual native-file excerpt from /home/loca/dev/quartz-sandbox/sandbox/vault/experiments/sandbox-tour.canvas, lines 33–42. This is an unchanged node-array fragment, including its trailing comma, not a shortened replacement JSON document:

    {
      "id": "title",
      "type": "text",
      "text": "# Sandbox Tour\n\nA native [JSON Canvas](https://jsoncanvas.org/spec/1.0/) page, rendered by `@quartz-community/canvas-page` at build time and made pannable and zoomable in the browser.\n\nThis canvas is content, not configuration: it lives at `vault/experiments/sandbox-tour.canvas`.",
      "x": 0,
      "y": 0,
      "width": 600,
      "height": 200,
      "color": "5"
    },

The same native file, lines 133–142, contains this complete file-node fragment pointing at a real vault page:

    {
      "id": "page-config",
      "type": "file",
      "file": "config/index.md",
      "x": 320,
      "y": 1250,
      "width": 280,
      "height": 100,
      "color": "2"
    },

What the rendered output proves

The prior capture in /home/loca/dev/quartz-sandbox/evidence/2026-09-15-quartz-migration-f1fd35c3/sandbox-experiments.json classifies this experiment as Native Canvas page. Its proof_route is /experiments/sandbox-tour.canvas.html, corresponding to the live generated Canvas page. The recorded proof_markers are exactly canvas_viewport: 1, canvas_nodes: 1, and canvas_node_ids: 20.

The browser capture records title sandbox-tour — Quartz Sandbox and 199483 bytes. The 20 node-ID matches and Canvas containers are evidence of native fixture output, not merely a code example on an explanatory page. That same captured DOM also contains mermaid_class: 6, katex_class: 7, callout_class: 17, callout_fold: 2, clipboard_button: 17, syntax_figures: 14, reading_stats: 7, reading_words: "623", reading_minutes: "3", and data_clipboard: 3; these are page-wide marker counts, not additional Canvas nodes or proof that every associated interaction worked.

The separate explanatory page, at /experiments/canvas-native-page.html, was captured with title Native Canvas Pages — Quartz Sandbox, 56661 bytes, and reading_stats: 1, reading_words: "313", reading_minutes: "2". Do not use that explanatory route as a substitute for the native fixture route.

These are prior Chrome DOM captures against the recorded build dist-1789511778 on the temporary loopback origin http://127.0.0.1:51963, not fresh observations of the linked public URLs. Chrome exited 0 for all 22 captured routes, with all_routes_raw_wikilinks: 0 and all_routes_internal_broken_class: 0. The receipt proves rendered DOM presence; it does not prove dragging, panning, zooming, popover interaction, visual fit, or a JavaScript-disabled experience. enableInteraction: true is configuration intent, not an interaction test. The receipt does not separately count the absent table of contents or right sidebar.

Safe for the shared engine?

Recorded assessment: safe_for_shared_engine: true.

Receipt reason, verbatim:

The page-type plugin claims only its own extension, so vaults without .canvas files retain their routes.

This is a recorded assessment, not deployment authority. A true verdict does NOT authorize a shared-engine change: any requirement to change /home/loca/dev/quartz/quartz must be reported as a BLOCKER, not an action. In particular, the sandbox’s layout override is not permission to change navigation across the 51 wikis served by that shared engine.

Try it in the sandbox

The sandbox-only rebuild command is:

cd /home/loca/dev/quartz-sandbox/sandbox && ./build.sh

The real wrapper /home/loca/dev/quartz-sandbox/sandbox/build.sh pins the isolated engine to commit 3dff48b5df6d84c9544a5ae19c8f2cbb01dc44e5 and rejects an engine outside the sandbox project. It takes a nonblocking .build.lock, runs npm run install-plugins BEFORE bootstrap-cli.mjs build, and passes --directory pointing to sandbox/vault and --output pointing to a fresh timestamped sandbox/dist-<epoch>. It checks that index.html exists before atomically swapping current. The origin sees the new release on the next request without a restart. The wrapper uses umask 022 and retains the new release plus two prior timestamped releases.

Recorded runtime invocation from sandbox-runtime.json, reference only:

PATH=/usr/bin:/bin PORT=51947 SANDBOX_ROOT=/home/loca/dev/quartz-sandbox/sandbox/current NODE_ENV=production /usr/bin/node /home/loca/dev/quartz-sandbox/sandbox/serve.mjs

The production service already owns port 51947. Do NOT start a second process or restart the service. The runtime receipt records an earlier manual-origin exercise; it is not an instruction to recreate that process. No sandbox rebuild or service change was performed to author this documentation.

index