Quartz:
- static site generator
npx quartz buildexecution path:
Server
entrypoint:
- command:
npx quartz build - target:
package.jsonbin→./quartz/bootstrap-cli.mjs
execution:
- Node executes
bootstrap-cli.mjsvia shebang
bootstrap-cli.mjs:
- CLI:
- parses arguments with yargs
- handles
pluginsubcommand
- bundling:
- transpiles/bundles TypeScript → JavaScript with esbuild
- imports
.scssas plain text through esbuild-sass-plugin v2 - bundles browser-targeted
*.inline.tsscripts through a custom esbuild plugin - imports inline-script modules as plain text
--serve:- starts WebSocket server on port
3001for hot-reload signals - starts HTTP file server on default port
8080 - watches
.ts,.tsx,.scss, package files - rebuilds through esbuild rebuild API
- starts WebSocket server on port
- build-module handoff:
- writes transpiled build module to
.quartz-cache/transpiled-build.mjs - dynamically imports it with a random query string to bypass Node import cache
- leak: ~350 kB per hot reload
- invokes module with parsed CLI arguments and client-refresh callback
- writes transpiled build module to
build.ts:
- setup:
- installs source-map support
- cleans output directory
- globs
content/files - respects
.gitignore
- Markdown parsing:
- concurrency:
- if content count >
128:- transpiles
quartz/worker.ts - spawns workerpool
- assigns 128-file batches to workers
- transpiles
- else:
- parses on main thread
- if content count >
- parser:
- workers/main thread instantiate unified parser from configuration
- steps:
- read file into vfile
- apply plugin text transformations
- slugify file path; see paths
- parse Markdown → mdast with remark-parse
- apply plugin Markdown-to-Markdown transformations
- convert mdast → hast with remark-rehype
- apply plugin HTML-to-HTML transformations
- concurrency:
- filtering:
- filters content through plugins
- emitting:
- gathers static resources
- transforms hast → JSX with hast-util-to-jsx-runtime and Preact
- renders HTML with preact-render-to-string; interactive hooks ignored
- assembles layout, client scripts, transpiled styles in
quartz/components/renderPage.tsx - minifies/transforms CSS with Lightning CSS
- splits scripts:
beforeDOMLoaded: inserts into<head>afterDOMLoaded: inserts into<body>
- writes emitted files to disk
--serve:- watches
.mdcontent files with 250 ms debounce - updates parsed AST/plugin-data content map for changed/new slugs
- reruns filters/emitters
- triggers client refresh
- watches
Client
initial_load:
- browser loads:
- HTML
public/index.css- critical JavaScript:
public/prescript.jsin<head>
deferred_load:
- browser loads non-critical JavaScript:
public/postscript.jsafter body
lifecycle_events:
"nav":- dispatched synthetically on page load
- if enableSPA option active: fires on client-side navigation to cycle event handlers/state
- if SPA disabled: fires once after initial load
"render":- dispatched after in-place DOM updates, such as decryption
- content-bound elements should listen for both
"nav"and"render"
Community Package Layering
packages:
@quartz-community/types:- type definitions
- interfaces
vfileDataMapaugmentation- no runtime dependencies
@quartz-community/utils:- shared path, DOM, sorting, date, JSX utilities
- depends on
@quartz-community/types
@quartz-community/runtime:- browser events, navigation, storage, script-loading utilities
- depends on
@quartz-community/typesand@quartz-community/utils
dependency_graph:
types (no deps)
↑
utils (depends on types)
↑
runtime (depends on types + utils)
↑
plugins (depend on any combination)
Plugin System
configuration:
- source:
pageTypesinquartz.config.yaml
community_plugins:
- clone into
.quartz/plugins/ - export through
.quartz/plugins/index.ts
Plugin Types
types:
- transformers:
- map over content
- examples: frontmatter, syntax highlighting
- filters:
- filter content
- examples: drafts, publication flags
- emitters:
- reduce over content
- examples: RSS, sitemaps, redirects, OG images
- page_types:
- render specific page categories
- examples: content notes, listings,
404 - routed by
PageTypeDispatcher
- Bases_views:
- custom view renderers for
bases-pagethroughViewRegistry - see making plugins > Bases Views
- custom view renderers for
- composition:
- plugins may span multiple types, such as transformer plus component provider
Plugin Resolution
npx quartz plugin add github:quartz-community/explorer:
- clones plugin to
.quartz/plugins/explorer/ - builds with
tsupviatsup.config.ts - re-exports through
.quartz/plugins/index.ts - locks commit hash in
quartz.lock.json
Plugin CLI Commands
commands:
npx quartz plugin add github:quartz-community/<name>: install pluginnpx quartz plugin install --latest: update all pluginsnpx quartz plugin install --clean: restore plugins fromquartz.lock.jsonnpx quartz plugin remove <name>: remove plugin
Plugin Structure
files:
src/index.ts: plugin entry point/exporttsup.config.ts: build configpackage.json: dependencies on@quartz-community/typesand@quartz-community/utils
details:
- see creating plugins
Page Frames
scope:
- frames define inner HTML structure inside static outer shell:
<html><head><body>#quartz-root
location:
quartz/components/frames/
files:
types.ts: definesPageFrameandPageFramePropsDefaultFrame.tsx: three-column layout; left sidebar, center, right sidebar, footerFullWidthFrame.tsx: single center columnMinimalFrame.tsx: content and footer onlyregistry.ts:FrameRegistrysingletonindex.ts: built-in registry andresolveFrame()
Frame Registry
registry:
FrameRegistrystores plugin-registered frames- plugins declare frames under
"quartz"."frames"inpackage.json - loader:
quartz/plugins/loader/frameLoader.ts
Frame Resolution
rendering:
quartz/components/renderPage.tsxcalls framerender()PageTypeDispatcher(quartz/plugins/pageTypes/dispatcher.ts) resolves frames
resolution_order:
- YAML config:
layout.byPageType.<name>.template - plugin-registered frame in
FrameRegistry builtinFramesmap- fallback:
"default"
output:
- active frame name writes to
data-frameon.page
Plugin-Provided Frames
plugin_frames:
- plugins export frames from
./framessubpath - plugins declare frames in manifest
- example:
canvas-pageprovides"canvas"frame - see making plugins > Providing Custom Frames
related: