What gets published
The site is Quartz v4.1.0, built from the vault, served at
garden.gillchristian.xyz. The vault is the content root, so a change to a
note is a change to the website.
Silence publishes
quartz/plugins/filters/explicit.ts:
const publishFlag: boolean = vfile.data?.frontmatter?.publish ?? true
return publishFlagA note with no publish key goes live. This is the single most important
fact about this repository.
Every note an agent creates must carry an explicit publish: key. Default to
publish: false; ask before setting true.
Only a bare false hides a note
quartz/plugins/transformers/frontmatter.ts parses with
yaml.load(s, { schema: yaml.JSON_SCHEMA }). JSON_SCHEMA resolves only the exact
lowercase token false to a boolean. Everything below is a truthy string,
and the note publishes:
| Written | Parses as | Result |
|---|---|---|
publish: false | boolean false | private |
publish: "false" | string | PUBLIC |
publish: no | string | PUBLIC |
publish: False / FALSE | string | PUBLIC |
Write the key with obsidian property:set name="publish" value="false" type="checkbox"
— type=checkbox produces a real unquoted boolean. Verified 2026-08-18.
The key is publish. Quartz ignores published.
ignorePatterns matches the root-relative path
quartz.config.ts ignores Inbox, Templates and Organization. Claude/ is
deliberately not ignored — this KB is published.
The pattern matches the path from the vault root, not the basename — so Inbox
protects only the top-level Inbox/. A note at Notes/Inbox-ideas.md would
publish. No such path exists today; the guard is fragile rather than broken.
The dot-entries in that list (.obsidian, .trash, …) are redundant: the glob
runs with dot: false.
The Assets hole
quartz/plugins/emitters/assets.ts globs ** minus **/*.md minus
ignorePatterns, and copies every match to the output. It never calls
shouldPublish. The filter in quartz/processors/filter.ts runs on markdown
content only.
Two consequences:
- Every file in
static/publishes, regardless of which note embeds it. A note being private does not make its attachments private. - Any non-markdown file publishes verbatim —
.bak,.csv,.txt,.pdf,.canvas. Two stale.md.bakfiles were removed on 2026-08-18 for this reason.
The audit script reports the current state of both. Read its output rather than recording an inventory here — see the note on exposure in index.md.
Never write a non-markdown file into the vault. Scratch files go outside
digital-garden/. This matters for any tool that generates a CSV or a report.
Fixing the mechanism means patching assets.ts to consult the same filter.
Not done — the current state was reviewed on 2026-08-18 and accepted.
Auditing
python3 .claude/skills/garden-publish-check/scripts/publish_audit.py
python3 .claude/skills/garden-publish-check/scripts/publish_audit.py --stagedThe script replicates the real pipeline (glob → ignorePatterns → RemoveDrafts → ExplicitPublish) plus the unfiltered Assets emitter. It exits 1 on a high-severity finding, so it can gate a push. Run it rather than trusting any count written here.
After the 2026-08-18 frontmatter cleanup every publishable note carries an
explicit publish key, so “public by default” should read 0. If it ever rises
above 0, new notes were created without one.
A push is a deploy
Vercel builds from master. There is no deploy definition in the repo, and
.github/workflows/ci.yaml is upstream Quartz CI, double-gated by
if: github.repository == 'jackyzha0/quartz' and branch v4, so it never runs
on this fork. vercel.json is only {"cleanUrls": true}.
Treat every push to master as a publish event. Run the audit first.
Dataview does not render
Quartz has no Dataview. A published note whose body is a Dataview query ships as
a raw code block. Books/Designing Data-Intensive Applications/00 …md is the
known case: its whole body is a query, which leaves its chapter notes unreachable
from the site.