# Quartz Build and Deploy Back to [[Obsidian/Self-Hosting with Quartz/Self-Hosting with Quartz|Self-Hosting with Quartz]]. ## Where to build: Enceladus (recommended) | | Build on Enceladus, copy `public/` to the NAS | Build on the NAS in Container Manager | |---|---|---| | Node | Already installed (v24.19.0, npm 11.17.0) | Needs a Node 22+ container | | Vault access | Local `H:` (Google Drive) | Needs the vault synced to the NAS (Cloud Sync / Drive) | | Speed | Fast desktop CPU | NAS CPUs are slow for about 2,000 notes plus images | | Automation | Fits the existing Sunday routine and scripts | A separate scheduler and logs on the NAS | | Downside | Enceladus must be on when the routine runs | More moving parts and harder debugging | → **Build on Enceladus** and mirror the finished `public/` folder to the NAS over SMB. ## Install (Quartz 5) Quartz 5 needs **Node 22 or later and npm 10.9.2 or later** (https://quartz.jzhao.xyz/). ```powershell cd C:\Users\jmars git clone https://github.com/jackyzha0/quartz.git quartz-pubprojects cd quartz-pubprojects npm i npx quartz create # pick a template, set baseUrl, choose an empty content folder npx quartz plugin install --from-config ``` - Keep the Quartz folder **outside Google Drive**, because `node_modules` and `public/` shouldn't sync. - This doesn't push anything to GitHub, and `npx quartz sync` isn't used. ## Configure: `quartz.config.yaml` Quartz 5 configures in YAML (https://quartz.jzhao.xyz/configuration): ```yaml configuration: pageTitle: "J. Marshall Pittman" baseUrl: notes.jmarshallpittman.org # no https://, no trailing slash enableSPA: true enablePopovers: true locale: en-US ignorePatterns: - .obsidian - .trash - Templates - "**/*.base" # until Bases rendering is tested - "**/*.{mp4,mov,mkv,avi}" ``` - `ignorePatterns` is a backstop. The staging step below already keeps out anything unpublished. - Quartz 5 has a **BasesPage** plugin (https://quartz.jzhao.xyz/features/bases), so `.base` files and ```` ```base ```` blocks may render. Test it in the preview. If they look wrong, keep them ignored and rely on the static `hub-list` and `folder-list` regions, which already work on the web. - **`publish.css` doesn't apply in Quartz.** Quartz uses its own theme and custom styles, which may be needed to hide leftovers such as `folder-overview` code blocks or the "Live view (in Obsidian)" headings. The note properties panel is controlled by the NoteProperties plugin's `includedProperties`. ## Choosing what gets published **Rule: the Obsidian Publish checkbox decides.** Don't add `publish: true`, because Obsidian Publish reads that property itself. Options considered: 1. **Quartz filter plugins.** - RemoveDrafts drops notes with `draft: true`. ExplicitPublish keeps only notes with `publish: true` (https://quartz.jzhao.xyz/features/private-pages). Neither one reads `dg-publish`. - A custom filter is possible but means writing a plugin. - **Quartz emits every non-Markdown file in `content/` regardless of filters.** Pointing Quartz at the whole vault would publish every image and video, including the ~762 MB of unpublished Events videos. ❌ 2. **Staging copy (recommended).** ✅ - `quartz_stage.py` reads the same public Publish file list that `pubprojects_weblists.py` uses. - It copies only the published `.md` notes, and the attachments those notes embed, into `content/`, keeping the folder structure. - It uses the same 50% safety guard. If the list fails to load, it falls back to `dg-publish: true`, which `--sync-dg` keeps identical to Publish. - Attachments come from the vault, not from Publish. If you later drop big image folders from Publish to save space, Quartz still carries them. - It skips video files and any single file over 50 MB, and lists them in its report. - It copies `Home.md` to `content/index.md` so it becomes the home page. - It cleans `content/` first, so unpublishing a note removes it from the site on the next build. ## Build and preview ```powershell cd C:\Users\jmars\quartz-pubprojects python C:\Users\jmars\quartz_stage.py --apply # refresh content/ npx quartz build --serve # preview at http://localhost:8080 npx quartz build # production build into public/ ``` ## Deploy to the Synology The Web Station site uses Apache 2.4, so add Quartz's `.htaccess` (from https://quartz.jzhao.xyz/hosting#using-apache) to `public/` before copying: ```apache RewriteEngine On ErrorDocument 404 /404.html RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI}.html -f RewriteRule ^(.*)$ $1.html [L] RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^(.*)/$ $1/index.html [L] ``` Mirror the site to the NAS with `quartz_deploy.ps1`: ```powershell robocopy C:\Users\jmars\quartz-pubprojects\public \\<NAS>\web\quartz /MIR /FFT /R:2 /W:5 /NP /LOG:C:\Users\jmars\quartz_deploy.log ``` - `/MIR` deletes files on the NAS that are no longer in `public/`. Always do a dry run with `/L` first, and never point it at anything but the site folder. - `/FFT` handles the NAS's coarser timestamps, so unchanged files aren't copied again. - The first deploy copies everything. After that, only changed files are copied. - Robocopy's exit codes 0–7 mean success. ## Weekly automation (planned) Sunday routine order: 1. `pubprojects_weblists.py --sync-dg --apply` 2. The storage check 3. `quartz_stage.py --apply` 4. `npx quartz build` 5. Robocopy deploy The routine **skips the deploy** if the build fails or the staged note count drops by more than 50% from last week. The report will add a line with the Quartz site size and the deploy result.