Quartz is a static site generator. How does it work?
This question is best answered by tracing what happens when a user (you!) runs npx quartz build in the command line:
npx quartz build, npm will look at package.json to find the bin entry for quartz which points at ./quartz/bootstrap-cli.mjs.esbuild configuration here is slightly special as it also handles .scss file imports using esbuild-sass-plugin v2. Additionally, we bundle ‘inline’ client-side scripts (any .inline.ts file) that components declare using a custom esbuild plugin that runs another instance of esbuild which bundles for the browser instead of node. Modules of both types are imported as plain text.--serve is set. This starts two servers:--serve flag is set, it also starts a file watcher to detect source-code changes (e.g. anything that is .ts, .tsx, .scss, or packager files). On a change, we rebuild the module (step 2 above) using esbuild’s rebuild API which drastically reduces the build times.quartz/build.ts), we write it to a cache file .quartz-cache/transpiled-build.mjs and then dynamically import this using await import(cacheFile). However, we need to be pretty smart about how to bust Node’s import cache so we add a random query string to fake Node into thinking it’s a new module. This does, however, cause memory leaks so we just hope that the user doesn’t hot-reload their configuration too many times in a single session :)) (it leaks about ~350kB memory on each reload). After importing the module, we then invoke it, passing in the command line arguments we parsed earlier along with a callback function to signal the client to refresh.build.ts, we start by installing source map support manually to account for the query string cache busting hack we introduced earlier. Then, we start processing content:content folder, respecting the .gitignore.quartz/worker.ts. Then, a work-stealing workerpool is then created and batches of 128 files are assigned to workers.useState, useEffect, or any other React/Preact interactive bits). Here, we also do a bunch of fun stuff like assemble the page [[layout]] from quartz.layout.ts, assemble all the inline scripts that actually get shipped to the client, and all the transpiled styles. The bulk of this logic can be found in quartz/components/renderPage.tsx. Other fun things of note:beforeDOMLoaded and afterDOMLoaded and are inserted in the <head> and <body> respectively.--serve flag was detected, we also set up another file watcher to detect content changes (only .md files). We keep a content map that tracks the parsed AST and plugin data for each slug and update this on file changes. Newly added or modified paths are rebuilt and added to the content map. Then, all the filters and emitters are run over the resulting content map. This file watcher is debounced with a threshold of 250ms. On success, we send a client refresh signal using the passed in callback function.<head> also links to page styles (emitted to public/index.css) and page-critical JS (emitted to public/prescript.js)public/postscript.js)"nav". This is used so client-side scripts declared by components can ‘setup’ anything that requires access to the page DOM."nav" event is also fired on any client-navigation to allow for components to unregister and reregister any event handlers and state."nav" event to just be fired a single time after page load to allow for consistency across how state is setup across both SPA and non-SPA contexts.The architecture and design of the plugin system was intentionally left pretty vague here as this is described in much more depth in the guide on [[making your own plugin]].