Contributing & conventions
Commit convention — Conventional Commits
Enforced by a commit-msg husky hook (commitlint + @commitlint/config-conventional).
Format:
<type>(<optional scope>): <subject>
Common types: feat, fix, docs, refactor, style, test, chore, ci, build.
Examples from history: feat(clipboard): option to copy paste actions between steps,
feat(types): ux improved. Keep the subject imperative and lower-case.
Branching & releases
- Work on
feature/*branches; merge intomain. - Pushing to
maindeploys the docs. - Pushing a git tag triggers
releases.yml, which builds and uploadsmain.js,manifest.json,styles.cssto a GitHub Release. The tag drives the release; keep it equal tomanifest.version. See the release checklist.
Code style
- TypeScript with
strictNullChecks,noImplicitAny,noUnusedLocals(seetsconfig.json).tsc -noEmitmust pass (it's the release gate). - Linting is
oxlint ./src. For Obsidian-guideline compliance, additionally run the officialeslint-plugin-obsidianmd(see scoring). - Imports use the bare-specifier aliases (
architecture,config,actions, …). - Logging goes through
logfromarchitecture(never bareconsole.*). - Obsidian API access goes through the
ObsidianApifacade / theVaultAPI — avoid touchingappglobally and avoid theAdapterAPI. - DOM is built with
createEl/createDiv/createSpan; clear withel.empty()— neverinnerHTML. - Styling uses CSS classes via the
c('name')helper (prefixzettelkasten-flow__) and SCSS partials undersrc/styles/components/— never inlineel.style.*. - UI text is sentence case and lives in the i18n layer (
architecture/lang/); add keys to bothen.tsandes.ts.
Styling architecture
src/styles/main.scss is a Dart-Sass aggregator (@use): utils/ (variables, animations,
mixins) → libraries/ (dragAndDrop) → components/ (14 partials) → a few global base rules.
Every class is zettelkasten-flow__<name>; the runtime helper c(...)
(architecture/styles/helper.ts, CSS_PREFIX = 'zettelkasten-flow') and the SCSS selectors must
stay in sync. Consume Obsidian CSS variables (--background-*, --interactive-accent, --text-*)
plus the local --zf-* custom props.
Adding a new action
An action is a 4-file bundle in src/actions/<name>/ plus one registration line. Use the
new-action harness skill to scaffold it, or do it by hand:
<Name>Action.tsx— aCustomZettelActionsubclass. Setid,defaultAction({ type, id, hasUI, ... }),getIcon(),getLabel(),link,purpose, and implementexecute(info)(write toinfo.content/info.contextbyzone) and/orpostProcess(info, file).<Name>Component.tsx— the build-time React UI (only ifhasUI: true); callprops.callback(value)to submit the user's value.<Name>Settings.ts(x)— the design-time config UI (ObsidianSettingrows and/or React). Follow an existing action (e.g.prompt) for the zone/key/label/static pattern.<Name>SettingsReader.ts— the read-only config view (used in community previews).- Register it in
src/main.ts → registerActions()and export the class fromsrc/actions/index.ts. - Document it under
docs/actions/<Name>.mdand add it to themkdocs.ymlnav.
See Actions & note builder for the full contract,
the zone model, and the DTOs your execute writes into.
Adding a settings section or handler
Settings sections are chain-of-responsibility handlers (AbstractChain<SettingsHandlerInfo>).
Add a handler under src/config/modals/handlers/ and wire it into the relevant section's chain
(General / Hooks / Developer). React-based handlers mount with createRoot and unmount on
refresh.
Pull-request checklist
- [ ]
npm run releasepasses (type-check + build). - [ ]
npm run lintis clean; ideallyeslint-plugin-obsidianmdtoo. - [ ] New UI strings are sentence case and in
en.ts+es.ts. - [ ] No
innerHTML/ inline styles introduced. - [ ] Docs updated (
docs/…+mkdocs.ymlnav) if behavior or API changed. - [ ] Commit messages follow Conventional Commits.
Release checklist
See the release harness skill for the automated version. In short:
- Bump
manifest.jsonversion(andmanifest-beta.jsonif used); ensureminAppVersionis correct. - Update / create
versions.jsonmapping the new version → itsminAppVersion. (Currently missing — restoreversion-bump.mjsto automate this. See Project health.) npm run releaseand verifydist/main.js+dist/styles.cssbuild.- Commit, then tag with the exact version (no
vprefix) and push the tag —releases.ymlcreates the GitHub Release with the three artifacts. - Confirm the release passes Obsidian's automated review (scoring).