image-gin

Half of Image Gin's settings went missing on Obsidian 1.14. 0.3.0 rebuilds the tab so that can't happen again

One bad row silently hid six settings sections. Image Gin 0.3.0 hands the whole tab to Obsidian's declarative settings API, and every setting becomes searchable.

Why Care?

We went looking for one setting: the ImageKit upload folder, still stuck on 2026-05 in October. It wasn't there. Neither were Magnific, Ideogram, the image cache, the drop gate, or Imgur. On Obsidian 1.14, Image Gin's settings tab drew the Recraft section and the size presets, then hit an old JSON editor and quietly stopped. No error, no notice: six sections just weren't there.

And for anyone who reached for Obsidian's settings search instead of scrolling, none of the settings existed even before the tab broke. Obsidian 1.13 only indexes plugins built on its new declarative settings API.

What's New?

  • The settings tab is rebuilt on Obsidian's declarative API. Image Gin describes its settings; Obsidian draws them and indexes them for search. A broken row can no longer take the rest of the tab down with it.

  • Every setting is searchable, including the ImageKit upload folder that started all this.

  • Image size presets are a native list with add, delete, and drag-to-reorder.

  • The image output folder gets Obsidian's folder picker.

  • V3 preset styles get real dropdowns. They never had any UI before; they lived behind a raw JSON editor that generation stopped reading in the V4.1 work.

  • ImageKit upload folders take {YYYY}, {MM}, {DD}, filled in at upload time.

  • Image Gin 0.3.0 requires Obsidian 1.13.

How we got here

We wrote the plan first ([[2026-10-06_Migrate-Settings-Tab-to-Obsidian-1-13-Declarative-API]]). Then came 14 acceptance tests, all failing, that the new tab had to satisfy:

  • every 0.2.x setting name survives

  • every control key exists in the settings shape

  • nested values read and write correctly

  • the custom style ID keeps its on/off flag in sync

A subagent wrote the rewrite against that spec. The 14 went green, all 54 tests passed, and ESLint's prefer-setting-definitions warning (open since the July toolchain pass) disappeared.

One thing the spec surfaced on the way: Obsidian's lint rules flag the 1.13-only APIs as unsupported unless minAppVersion says 1.13. So the version bump to 0.3.0 isn't paperwork. It's what makes the new tab legal.

Under the Hood

0.2.30.3.0
RenderingImperative display(), ~1,100 linesgetSettingDefinitions()
SearchNot indexedEvery row by name and description
Nested keysHand-wired per rowgetControlValue/setControlValue with dot paths
Size presetsHand-drawn rows + "Add new size"type: 'list' with addItem, onDelete, onReorder
minAppVersion1.8.101.13.0

Toolchain (b367b4c): ESLint 10.12, typescript-eslint 8.71.1, eslint-plugin-obsidianmd 0.4.2, esbuild 0.28.2, obsidian 1.13.1. Two packages are held on purpose:

  • TypeScript stays on 6.0.3. typescript-eslint supports only <6.1.0, so moving to 7 would break the review bot's typed rules.

  • @types/node stays on 22. In-app Obsidian updates don't replace Electron, so a 1.13 user can still be on Node 22.

pnpm-workspace.yaml now carries both onlyBuiltDependencies (pnpm 10, which CI uses) and allowBuilds (pnpm 11+).

What's Next

  • Walk the new tab in Obsidian. The unit tests can't settle one question: whether update() repaints an open tab when a toggle reveals dependent rows.

  • Tag 0.3.0. The release narrative is ready at changelog/releases/0.3.0.md.