Project Layout
What canary init writes into a fresh project, and why each piece exists.
canary.jsonc— the project's config. See Reference → canary.jsonc for every field. Gets an"initialized": truemarker so a laterinitrun against the same directory knows to refuse (unless you pass--force).shell.html— the page chrome (<head>, header/nav,<main id="app">, footer) every generated page is stamped into. Copied from Canary's own generic starter — edit it to change the site's structure, not just its colors.css/framework.css— generic layout only (header, nav dropdown, footer,#app). Not meant to need per-site edits; brand decisions live intheme.cssinstead, as CSS custom properties (--bg,--accent, etc.) framework.css already reads.css/theme.css— your actual branding: colors, and (if you want a different logo/title treatment) the.site-logo/.site-titlerules. Starts as a copy of framework.css's own default values, so it's immediately usable, not an empty file.tools/curtain.csandtools/reading-time.ps1— two working content-toolchain tools, registered incanary.jsonc'stoolsmap but not applied anywhere yet.curtain.csis a passthrough (reads stdin, writes it back unchanged, and prints the toolchain env vars to stderr).reading-time.ps1is a real word-count badge: it counts words and inserts a reading-time estimate after the page's first heading. Deliberately two different languages, not one: a tool is just an external command, andcurtain.cs(C#, needs a .NET SDK) next toreading-time.ps1(PowerShell, ships with Windows, no separate runtime to install) makes that visible instead of implied.canary.jsonc's entry forcurtainalso shows, commented out, the precompiled-tool form (canary tools build curtain). Copy or rename either as a starting point once you want a real one — see Guide → Content Toolchain.content/index.md— your home page. This is real content, not framework scaffold, soinitnever overwrites it, even with--force.widgets/— ifcopyDefaultsOnInitwas left on (the default), editable local copies of every built-in widget (downloads,slideshow,code). Site-authored widgets win over built-in ones on a name collision, so these become the active versions immediately. See Guide → Widgets.root-copy/— starts empty. Anything placed here is copied verbatim tooutput.dir's own root, every build — the escape hatch for files a host looks for by a fixed name at the site's actual root (GitHub Pages'CNAME,.nojekyll, arobots.txt/favicon.icooverride) that can't live undercontent/(which always nests underoutput.dir/content/...) or any other Canary-owned subdirectory. Copied last, so aroot-copy/file always wins over anything Canary generated at the same path..gitignore— ignorestools/bin/(wherecanary tools buildputs precompiled tool binaries) and generic editor/OS cruft.output.diris deliberately not ignored by default — it defaults todocsspecifically to match GitHub Pages' "serve from/docsonmain" convention, which needs that directory committed — but the line to ignore it is there, commented out, if you deploy some other way. Likecontent/index.md, this file is never overwritten once it exists — you're expected to add your own entries to it over time.
Every file above except content/index.md and .gitignore is overwritten on every init run against the same directory (with --force), by design — these files are meant to track Canary's current defaults, not freeze at whatever version you first scaffolded against.